I have a class that has several collections associated with it, all of which need to be fetched eagerly when an instance of the class is loaded. However, I get the usual "cannot simultaneously fetch multiple bags" exception - unfortunately "classic" solutions for this problem don't work in this case (see the explanation below), so I've decided to create a PostLoadEventListener for this class that calls Hibernate.initialize(myObject) manually, forcing the joined collections to be loaded immediately (not nice, but I can't think of anything else now).
The problem is that even though the session's still supposed to be open within the PostLoadEventListener (session.get() is invoked within a Spring HibernateTemplate), I get a LazyInitializationException ("failed to lazily initialize a collection, no session or session was closed") when trying to call Hibernate.initialize() on the object (the same happens when calling a lazy collection's getter).
What could be wrong here?
Hibernate version:
3.2.5ga
Mapping documents:
Code:
class MyClass {
@CollectionOfElements(fetch = FetchType.LAZY)
@JoinTable(name = "other_table", joinColumns = { @JoinColumn(name = "fk_in_other_table") })
public List<MyOtherClass> getMyCollection() {
return myCollection;
}
...
}
Code between sessionFactory.openSession() and session.close():The dao code (wrapped in a HibernateTemplate):
Code:
T entity = (T) session.get(persistentClass, id);
The listener:
Code:
public class EagerLoader implements PostLoadEventListener {
public void onPostLoad(PostLoadEvent event) {
Object loadedEntity = event.getEntity();
if (loadedEntity instanceof MyClass) {
MyClass myLoadedObject = (MyClass) loadedEntity;
// This displays "Session open? true"
Session session = event.getSession();
log.info(MessageFormat.format("Session open? {0}", session.isOpen()));
// This throws a LazyInitializationException
Hibernate.initialize(loadedObject);
}
}
}
Full stack trace of any exception that occurs:
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection, 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.readSize(AbstractPersistentCollection.java:97)
at org.hibernate.collection.PersistentBag.size(PersistentBag.java:225)
at mypackage.onPostLoad(EagerLoader.java:30)
at org.hibernate.engine.TwoPhaseLoad.initializeEntity(TwoPhaseLoad.java:201)
at org.hibernate.loader.Loader.initializeEntitiesAndCollections(Loader.java:854)
at org.hibernate.loader.Loader.doQuery(Loader.java:729)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236)
at org.hibernate.loader.Loader.loadEntity(Loader.java:1860)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:48)
at org.hibernate.loader.entity.AbstractEntityLoader.load(AbstractEntityLoader.java:42)
at org.hibernate.loader.entity.BatchingEntityLoader.load(BatchingEntityLoader.java:82)
at org.hibernate.persister.entity.AbstractEntityPersister.load(AbstractEntityPersister.java:3044)
at org.hibernate.event.def.DefaultLoadEventListener.loadFromDatasource(DefaultLoadEventListener.java:395)
at org.hibernate.event.def.DefaultLoadEventListener.doLoad(DefaultLoadEventListener.java:375)
at org.hibernate.event.def.DefaultLoadEventListener.load(DefaultLoadEventListener.java:139)
at org.hibernate.event.def.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:195)
at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:103)
at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:878)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:815)
at org.hibernate.impl.SessionImpl.get(SessionImpl.java:808)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at org.springframework.orm.hibernate3.HibernateTemplate$CloseSuppressingInvocationHandler.invoke(HibernateTemplate.java:1219)
at $Proxy20.get(Unknown Source)
... 29 more
Name and version of the database you are using:
Oracle 10g
Thanks,
Peter
PS. the reason why I can't solve this by converting the collections into sets is that these are composite elements, and according to chapter 8.2 of the documentation composite elements cannot be stored in sets if they have nullable properties. Also, it's a legacy database, so I can't add an @IndexColumn to get rid of the bag semantic.