[hibernate-dev] Implement UserCollectionType for non-Collection types such as Guava's Multimap

Steve Ebersole steve at hibernate.org
Tue Apr 25 09:56:20 EDT 2017

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 at 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

More information about the hibernate-dev mailing list