... until the collector arrives ...

This "blog" is really just a scratchpad of mine. There is not much of general interest here. Most of the content is scribbled down "live" as I discover things I want to remember. I rarely go back to correct mistakes in older entries. You have been warned :)

2007-08-22

Hibernate 3.3: Lazy Collections vs. Multiple Sessions

Using Hibernate, there is a problem with lazy-loaded collections in detached objects.  Consider this sequence of events.  In one session, load an object with a lazy-loaded collection property.  Close the session and open a new session.  Associate the object with the new session.  Access an element of the collection (e.g. myCollection.first()).  The following exception occurs:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: MyEntity.myCollection, no session or session was closed
	at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
	at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
	at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:343)
	at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
	at org.hibernate.collection.PersistentSortedSet.first(PersistentSortedSet.java:93)

A quick trip in the debugger shows that the session is closed.  Apparently, attaching an entity to a session does not attach its lazy collection properties.  So, how does one do that?  Well, you could try Hibernate.initialize(myCollection).  But then you would get:

org.hibernate.HibernateException: disconnected session
	at org.hibernate.collection.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:452)
	at org.hibernate.Hibernate.initialize(Hibernate.java:309)

Perhaps mySession.lock(myCollection, LockMode.NONE)?  Nope, this gives:

org.hibernate.MappingException: Unknown entity: org.hibernate.collection.PersistentSortedSet
	at org.hibernate.impl.SessionFactoryImpl.getEntityPersister(SessionFactoryImpl.java:550)
	at org.hibernate.impl.SessionImpl.getEntityPersister(SessionImpl.java:1338)
	at org.hibernate.event.def.DefaultLockEventListener.onLock(DefaultLockEventListener.java:50)
	at org.hibernate.impl.SessionImpl.fireLock(SessionImpl.java:584)
	at org.hibernate.impl.SessionImpl.lock(SessionImpl.java:576)

Okay, surely this will work:

PersistentCollection collection = (PersistentCollection) myCollection;
collection.setCurrentSession((SessionImplementor) mySession);
Hibernate.initialize(myCollection);

Nope:

org.hibernate.HibernateException: collection was evicted
	at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:38)
	at org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1716)
	at org.hibernate.collection.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:454)
	at org.hibernate.Hibernate.initialize(Hibernate.java:309)

onInitializeCollection is calling PersistenceContext.getCollectionEntry(collection) and coming up empty -- the new session has no clue about the collection.

I'm stumped.  I can't figure out how to bring an uninitialized collection into a new session.  It looks like you must initialize a collection in the session that first accesses it.

Blog Archive