aspose file tools*
The moose likes Object Relational Mapping and the fly likes EJB3 org.hibernate.LazyInitializationException:failed to lazily initialize a collection of role Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of The Java EE 7 Tutorial Volume 1 or Volume 2 this week in the Java EE forum
or jQuery UI in Action in the JavaScript forum!
JavaRanch » Java Forums » Databases » Object Relational Mapping
Bookmark "EJB3 org.hibernate.LazyInitializationException:failed to lazily initialize a collection of role" Watch "EJB3 org.hibernate.LazyInitializationException:failed to lazily initialize a collection of role" New topic
Author

EJB3 org.hibernate.LazyInitializationException:failed to lazily initialize a collection of role

Nitin Bhardwaj
Ranch Hand

Joined: Feb 02, 2007
Posts: 72
Hi Friends,
I am using EJB3 and Struts in my application. The relationship between the entities Employee and LeaveApprovalHierarchy is OneToMany bidirectional. The relevant code listings for the two entities is given below:

1. Employee



2. LeaveApprovalHierarchy


Following is the Session bean code that retrieves the Employee entity by its employee code:


and the following is the code in the Action class that is printing the employee info to console:


Observation 1: When I execute the above code then Employee information which is not loaded Lazily is shown fine but while retrieving LeaveApprovalHierarchy from employee object it throws the following exception:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.nit.ejb.entity.Employee.leaveHierarchy, no session or session was closed
Observation 2: When I specify the FetchType to be EAGER rather than LAZY for LeaveApprovalHierarchy in the Employee entity then no exception is thrown and it executes perfectly.
Question: What is the correct way of implementing LAZY fetch for OneToMany relationships? Can somebody provide some code while explaining what should be done in the example above to correctly implement LAZY fetch?
Thank You !

Best Regards,
Nitin Bhardwaj
xsunil kumar
Ranch Hand

Joined: Dec 14, 2009
Posts: 133
Nitin,

If your fetch type is Lazy then you need to fetch associated object before closing your hibernate session. If you have closed your hibernate session and try to fetch it , it will throw above mentioned exception. One way to resolve this is to put fetch type = Eager. Otherwise write some block of code inside your findEmployeeByEmployeeNumber method to access LeaveApprovalHierarchy object. means your code should like

public Employee findEmployeeByEmployeeNumber(String employeeCode) throws Exception
{
Query q=entityManager.createNamedQuery("findEmployeeByEmployeeNumber");
q.setParameter("employeeCode", employeeCode);
if (q.getResultList().size() <= 0)
return null;
Employee employee=(Employee)q.getSingleResult();
// write code block to fetch LeaveApprovalHierarchy object.

Set <LeaveApprovalHierarchy> sL1=emp.getLeaveHierarchy();
Iterator<LeaveApprovalHierarchy> i1=sL1.iterator();
LeaveApprovalHierarchy l1=null;
System.out.println("Printing Leave Approval Hierarchy objects:");
while(i1.hasNext())
{
l1=i1.next();
System.out.println("AHID:"+l1.getAHID());
System.out.println("Approval Level:"+l1.getApprovalLevel());
System.out.println("Approver Emp ID:"+l1.getApproverEmpIDFK());
System.out.println("Employee ID:"+l1.getEmployeeIDFK());
System.out.println("---------- Next Line-------------");
}

return employee;
}

above is only sample to do this. You need to rectify above code.

Hope this will solve your problem.

Sunil
Nitin Bhardwaj
Ranch Hand

Joined: Feb 02, 2007
Posts: 72
xsunil kumar wrote:Nitin,
..............................
...............................
Employee employee=(Employee)q.getSingleResult();
// write code block to fetch LeaveApprovalHierarchy object.

Set <LeaveApprovalHierarchy> sL1=emp.getLeaveHierarchy();

Iterator<LeaveApprovalHierarchy> i1=sL1.iterator();
................................
................................
above is only sample to do this. You need to rectify above code.

Sunil


Hi Sunil Thanks for replying !
By adding a code block to fetch LeaveApprovalHierarchy do you mean that I should write some code to fetch it without using employee object's method (emp.getLeaveHierarchy()) independently? If your answer is yes that I think it will mean to fetch the Set of LeaveApprovalHierarchy entities by some method which uses EntityManager and then setting this retrieved set of entities to the employee object by calling emp.setLeaveHierarchy(Set leaveHierarchy).....
Please correct me if I am going in the wrong direction. (I am using EJB3 not Hibernate in my application. However, JBoss uses Hibernate to implement it under the hood).
Thank You !
Regards,
Nitin
xsunil kumar
Ranch Hand

Joined: Dec 14, 2009
Posts: 133
No Nitin, i think you understood something wrong. Bottom line is that , Hibernate will not load associated entities if fetch type is Lazy. It will load assocaited entity on demand but session should be open. Now in your case what is happening, Hibernate has loaded Employee entity not not loaded LeaveApprovalHierarchy object by default as its fetch type is lazy. After closing your hibernate session, you are trying to get LeaveApprovalHierarchy object from employee which will throw the exception.

For avoiding this exception, you need to force hibernate to load LeaveApprovalHierarchy object also along with employee. As hibernate will do this on demand and session should be open. The way to do is after getting employee object , get LeaveApprovalHierarchy by employee.<get method of LeaveApprovalHierarchy object> and access these values of LeaveApprovalHierarchy object. So what will happen, up to this instance your session is not closed and you are trying to fetch LeaveApprovalHierarchy object from employee object so it will create ondemand rule and hiberante will load this entity also.
After that you can close your hibernate session.

Employee employee=(Employee)q.getSingleResult();
// write code block to fetch LeaveApprovalHierarchy object.

Set <LeaveApprovalHierarchy> sL1=employee.getLeaveHierarchy(); /// Here you are using employee which is returned by hibernate session.
Iterator<LeaveApprovalHierarchy> i1=sL1.iterator();
//creating on demand request.

session.close(); // closing hibernate session.

Sorry for previous code as by mistake i have typed emp in place of employee.

Hope this will help you.

Sunil
xsunil kumar
Ranch Hand

Joined: Dec 14, 2009
Posts: 133
One more thing, entity manager and hibernate works on same principle. There is nothing much difference.
Nitin Bhardwaj
Ranch Hand

Joined: Feb 02, 2007
Posts: 72
xsunil kumar wrote:

For avoiding this exception, you need to force hibernate to load LeaveApprovalHierarchy object also along with employee. As hibernate will do this on demand and session should be open. The way to do is after getting employee object , get LeaveApprovalHierarchy by employee.<get method of LeaveApprovalHierarchy object> and access these values of LeaveApprovalHierarchy object. So what will happen, up to this instance your session is not closed and you are trying to fetch LeaveApprovalHierarchy object from employee object so it will create ondemand rule and hiberante will load this entity also.
After that you can close your hibernate session.

Employee employee=(Employee)q.getSingleResult();
// write code block to fetch LeaveApprovalHierarchy object.

Set <LeaveApprovalHierarchy> sL1=employee.getLeaveHierarchy(); /// Here you are using employee which is returned by hibernate session.
Iterator<LeaveApprovalHierarchy> i1=sL1.iterator();
//creating on demand request.

session.close(); // closing hibernate session.


Sunil


Hi Sunil,
Thanks again for replying !
I got the things that I was doing wrong previously. If you look at the following code which is present in my Session Bean class:


Previously I didn't use an Iterator in above method which is why it was not fetching the LeaveApprovalHierarchy ! Now when I added this it fetched it just after fetching the employee object ! So it worked fine. I also learned that if I try to paste above lines in my action class (and not in above method which actually uses an EntityManager) then the exception will be thrown because the session (in Hibernate terms) or EntityManager (in EJB terms) will be closed after we exit from findEmployeeByEmployeeNumber() method.
Nice things learned ! And after this message I guess my another question on the same topic is getting ready !
Thank you !
Regards,
Nitin
xsunil kumar
Ranch Hand

Joined: Dec 14, 2009
Posts: 133
Good Luck Nitin, and i am happy that your issue has been resolved.
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
 
subject: EJB3 org.hibernate.LazyInitializationException:failed to lazily initialize a collection of role