Hi Jan-Willem,
See comments in-line.
Overall though, I wanted to mention that starting in 6.0 we will be
introducing a redesigned Type SPI to hopefully address some shortcomings,
some of which you bring up. I hope you add your input to some of those
discussion threads on this list about that redesign.
On Mon, Apr 24, 2017 at 2:02 PM Jan-Willem Gmelig Meyling <
jan-willem(a)youngmediaexperts.nl> wrote:
Hi everyone,
Out of curiosity I’ve tried to implement a UserCollectionType for Guava’s
Multimap [1] based on this [2] article thats doing a similar job for
Apache’s MultiMap. Doing so I’ve stumbled upon two issues, for which I’d
like to receive some feedback.
As far as I can see, the UserCollectionType seems focussed around mapping
values to indexes. In the case of a list this would supposedly be a number,
for non-ordered collections I am not sure, but for maps it seems to be the
entries' key. It seems that the implementation for Apache’s MultiMap
actually is a Map<K, Collection<V>> so that in the UserCollectionType
mentioned in that article every index actually points to a collection of
values under that key. I am wondering whether this could potentially break
the behaviour for the UserCollectionType class as it seems it should be
possible to dirty check the values behind the indexes which probably
doesn’t work against collections.
Simply stated (as the article even mentions), Hibernate does not support
collections of collections. In fact JPA even explicitly says this is not
supported, although granted implementors can choose to provide such a
feature as an extension. As discussed in the article that would be
multi-map support as opposed to map support. The article shows this can
"be done" but this is a case of using something as it was not intended to
be used.
This is definitely something we would look at supporting in 6.0's type
redesign. Vlad and I have specifically talked about supporting
database/JDBC ARRAY types. That is still quite different from the model
described in the article though, so we'd have to see if supporting that
kind of model fits in what we want to do or if we can support it with
minimal changes. Again, I'd suggest getting involved in those discussions.
But there’s another inconvenience I stumbled upon while implementing
this.
Where the Apache MultiMap extends a Map<K, Object>, Guava’s Multimap does
not. I therefore had to override the TypeUtils, JavaXCollectionType,
CollectionBinder, ArrtirubteFactory, PluralAttributeImpl, and most likely
if I wanted to do it well a MapBinder and PluralAttribute’s CollectionType
as well. While doing this I also found out that
JavaXCollectionType.getCollectionClass() returns Map.class perfectly fine
for the currently supported Map fields, even though they do not satisfy the
<? extends Collection> return type.
So it seems this is a bad idea after all ;-) But I am wondering whether I
am missing something here.
Nope :) Again, its not something that is supported and it is definitely
not baked into these contracts. We support the Java collection types.
Likely that won't change. But if its easy enough to add support for other
types, we would consider it for 6.0.
a) Is there a way to map a Map<Key, Collection<Value>> as an
EnumeratedCollection in plain Hibernate?
No. Again, "collections of collections" are not supported.
b) Is there another way to achieve the above and persist a Guava
Multimap
with a custom user type? (Assuming the UserCollectionType is not the right
place to start)
So again no.
c) Is Hibernate 6 going to change the answer to these questions?
Yes, supposing someone champions them in the 6.0 type redesign discussions
;)
d) Was the article ever right about how to persist Apache’s
MultiMap’s
type, or was it based on false assumptions on the use of UserCollectionType
anyways?
So long as it is true that the nested collection is only ever a "bag"[1],
then I could see this possibly working. I have not looked at the code for
the article so I cannot say if it makes that assumption or not.
[1] An non-ordered, non-unique collection