-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: Forcing LAZY collections to load in a PostLoadEventListener?
PostPosted: Wed Jan 16, 2008 8:44 am 
Newbie

Joined: Wed Jan 16, 2008 8:23 am
Posts: 7
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.


Top
 Profile  
 
 Post subject: Workaround
PostPosted: Wed Jan 16, 2008 10:27 am 
Newbie

Joined: Wed Jan 16, 2008 8:23 am
Posts: 7
I've found a workaround: if the persistent object implements interface Lifecycle, it can define its own onLoad(), etc. methods which work just like the @PostLoad annotations used by Hibernate's EntityManager (but while the latter cannot be used with the SessionManager, the Lifecycle can). When calling a LAZY getter from the onLoad() method, Hibernate loads the elements of the associated collection.

However, I'd still be interested in the reason why my original solution threw a LazyInitializationException.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.