• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Tim Cooke
  • Liutauras Vilda
  • Jeanne Boyarsky
  • paul wheaton
Sheriffs:
  • Ron McLeod
  • Devaka Cooray
  • Henry Wong
Saloon Keepers:
  • Tim Holloway
  • Stephan van Hulst
  • Carey Brown
  • Tim Moores
  • Mikalai Zaikin
Bartenders:
  • Frits Walraven

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

 
Ranch Hand
Posts: 72
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
 
Ranch Hand
Posts: 147
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 72
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 147
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
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
Posts: 147
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
One more thing, entity manager and hibernate works on same principle. There is nothing much difference.
 
Nitin Bhardwaj
Ranch Hand
Posts: 72
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

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
Posts: 147
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Good Luck Nitin, and i am happy that your issue has been resolved.
 
Wanna see my flashlight? How about this tiny ad?
Gift giving made easy with the permaculture playing cards
https://coderanch.com/t/777758/Gift-giving-easy-permaculture-playing
reply
    Bookmark Topic Watch Topic
  • New Topic