Hi Steve,
Thanks for your response to my questions! Good to see that my intuition was right that
this was currently not so trivial if even possible to do. I’ll read up on the 6.0 code
base as I am definitely willing to join the ride for Hibernate 6. What is the current
status of the Hibernate 6.0 type redesign?
What I was wondering though is whether the support of JDBC array types would pave the way
for array-based subselect fetching of to-many relations. I am thinking of for example
Postgresql’s array_agg function. In some of our more complex domain entities I’ve been
struggling with eagerly fetching multiple to-many relations or deeper to-many relations
without getting a relatively large cross product. I currently do use subselect fetching
for this but I think having the ability to inline rows (perhaps even recursively) in
arrays would decrease query time, number of queries and result set size significantly.
Kind regards,
Jan-Willem
On 25 Apr 2017, at 15:56, Steve Ebersole <steve(a)hibernate.org>
wrote:
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 <mailto:jan-willem@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