Collection is not associated with any session exception when doing an eager fetch on a non-unique collection.
Description
Attachments
Activity
Christian Beikov January 3, 2025 at 2:27 PM
Usually, a wrong collection mapping where the key of a collection can be associated with multiple entity objects results in the Found shared references to a collection
error on flush, which is pretty confusing, because this should rather be a load time error IMO. For some reason which I have yet to find out, the code in StatefulPersistenceContext
allowed this to happen rather than throwing immediately.
I will investigate this, but beware that the expectation is that a collection key is unique. Join columns must form a unique key for a collection role such that a collection key can only ever be associated to a single entity primary key.
Some common errors that lead to this are:
Using join columns for which no unique constraint exists
Missing a unique constraint on all the join columns of a join table
If you look at the schema that Hibernate ORMs hbm2ddl tool would suggest and you notice unexpected constraints, this should raise a red flag that something is not right in your mapping.
Wenjie Zhang July 25, 2017 at 2:10 AM
@Gail Badner, I have checked the hibernate log and do not see any warnings.
Wenjie Zhang July 10, 2017 at 3:44 PM
We have exactly the same issue with hibernate 4.3.11.
Former user September 17, 2016 at 1:17 AM
, do you see any warnings logged due to and HHH-9777, both fixed in 4.3.11?
Carlos Lopes September 16, 2016 at 8:46 PM
Same for me on Hibernate 4.3.11.Final.
On Hibernate 5 the issue seems to have been fixed.
However, the issue is not specific to eager loading, I still get the error when doing lazy loading, it's just a different exception at a different point:
EAGER:org.hibernate.HibernateException: collection is not associated with any session
LAZY:org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: <path>, could not initialize proxy - no Session
Interestingly enough if I add a breakpoint to line 825 of StatefulPersistenceContext
and step through the execution the issue does NOT happen. If I move the breakpoint to line 822 the issue still happens. I haven't debugged any further to know what is really going on, but it will always work if I have the breakpoint on line 825 and always fail if I don't.
One way to work around this is to convert the one-to-many relationship to a many-to-many using the same table as the join table. This thread from 2009 has more details about the workaround.
It is basically caused by having an eager collection where the key of the collection is not unique in the results.
The code works as follows in CollectionType.getCollection():
....
persistenceContext.addUninitializedCollection( persister, collection, key );
// some collections are not lazy:
if ( initializeImmediately( entityMode ) ) {
session.initializeCollection( collection, false );
}
else if ( !persister.isLazy() ) {
persistenceContext.addNonLazyCollection( collection );
}
if ( hasHolder( entityMode ) ) {
session.getPersistenceContext().addCollectionHolder( collection );
}
if persistenceContext.addUninitializedCollection() detects that the collection with the given key has already been added it clears the session on the old instance of the collection (sets it to null). However, that collection has already been added to the persistence context by an earlier call to this method. So later when StatefulPersistenceContext.initializeNonLazyCollections() is called it iterates through all of the collections in the persistence context (including those which have had their session set to null by addUninitializedCollection()), calling forceInitialization() which throws a 'collection is not associated with any session' exception.