2

I'm wondering why I'm getting this exception while trying to get a list of object attached to an object, but I get lazy exception instead when the list is null:

For example:

protected static final String hqlRequest = "select user from User as user";
        
final StringBuilder sbHqlRequest = new StringBuilder(hqlRequest);
sbHqlRequest.append(" left outer join fetch user.listeCondition as condition");     
sbHqlRequest.append(" left outer join fetch user.listeReponse as reponse");
sbHqlRequest.append(" left outer join fetch reponse.listeCat reponseCat");
sbHqlRequest.append(" left outer join fetch reponseCat.listeDomain listeDomain");
sbHqlRequest.append(" left outer join fetch reponse.listePlan reponsePlan");
        

sbHqlRequest.append(" where user.identifiant=? ");
return (User) session.createQuery(sbHqlRequest.toString()).setInteger(0, identifiant.intValue()).uniqueResult();

I'm getting a lazy when trying to access reponseCat.listeDomain. In my DB there is no list, but I was waiting for null, not an exception.

Am I doing something wrong or is that how Hibernate works?

Exception:

Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: Cat.listeDomain - no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:191)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:183)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:48)
at org.hibernate.collection.PersistentSet.isEmpty(PersistentSet.java:118)
at org.apache.commons.collections.CollectionUtils.isEmpty(CollectionUtils.java:979)
at org.apache.commons.collections.CollectionUtils.isNotEmpty(CollectionUtils.java:992)

I noticied that: when I use the session passed in param, I get the lazy exception, but when I create a local session it works, but I get my objects associated with two different sessions!

VLAZ
  • 26,331
  • 9
  • 49
  • 67
Kirikou
  • 43
  • 6
  • Possible duplicate of [Hibernate "No session or session was closed" when i trying to get data from database](http://stackoverflow.com/questions/13264799/hibernate-no-session-or-session-was-closed-when-i-trying-to-get-data-from-data) – Vivek Singh Dec 24 '15 at 10:50
  • Thanks Vivek Singh, but I don't want to use lazy = false, I'd rather fetch it when I need it. – Kirikou Dec 24 '15 at 11:04
  • Just want to comment that you should avoid building the query string at run time and instead use `+` to concatenate static or literal string fragments. The compiler will evaluate these at compile time which allows Hibernate to lookup the query plans from cache quickly. – billc.cn Dec 24 '15 at 12:09
  • you could also use (see https://stackoverflow.com/questions/25362831/solve-hibernate-lazy-init-issue-with-hibernate-enable-lazy-load-no-trans) – Raphael Roth Dec 24 '15 at 12:29

2 Answers2

0

This error shows that you are accessing the field when the session is closed. Generally what happens in lazy loading as the transaction is different in such a case. You may require to load it initially only using eager loading.

call the size() method on the fetched collection from the same method as below

User user = (User) session.createQuery(sbHqlRequest.toString()).setInteger(0, identifiant.intValue()).uniqueResult();
user.getListeDomain().size();
user.getListeCondition().size();
....
//other collections
return user;
Vivek Singh
  • 2,047
  • 11
  • 24
  • That's why I can't understnd, the session has never been closed. Otherwise I wouldn't have been able to get all the other collections and stuff!! – Kirikou Dec 24 '15 at 11:03
  • Once you do the query and move further the session is closed by hibernate itself. You can do one thing at the movement call the size() method on listeDomain after you get your user object in the same method from where you are doing the query. – Vivek Singh Dec 24 '15 at 11:07
  • I didn't know that hibernate closes the session itself when I move further, thanks for the information. But I still don't understand how can I get the other collections? with the same session!! – Kirikou Dec 24 '15 at 11:09
  • call the size() function on every collection once you have the user object let me update my answer with the same. – Vivek Singh Dec 24 '15 at 11:10
  • Calling the size() method throws once again lazy exception!! – Kirikou Dec 24 '15 at 11:12
  • Are you calling the size method in the same function from where you are executing the query? – Vivek Singh Dec 24 '15 at 11:13
  • Yes, same method where I'm excuting the query – Kirikou Dec 24 '15 at 12:59
0

When I ran into this problem I had to execute a separate query to see if that list had any results. If it didn't have any results then I put an empty list into the result with a new List<>(); statement. So, for example:

List<> result = query.setParameter(0, owner.id).getResultList();
if ( result.size() > 0 ) 
    owner.setList(result);
else
    owner.setList(new List<>() );

This removes the hibernate managed list that is flagged as not initialized because there were no results for that owner in the database.

K.Nicholas
  • 10,956
  • 4
  • 46
  • 66