How to avoid LazyInitializationException in Hibernate?
Lazy collections work only within the scope of the transaction (where the owning entity was retrieved from a DB). In other words, you should not pass a Hibernate entity with non-loaded lazy sub-entities or collections outside the transaction scope.
You need either to build another entity or use lazy="false" if you want to pass an entity to JSP, or serialization code or anything else.
J Ellis
I am a software engineer and intellectual property attorney.
Updated on June 04, 2022Comments
-
J Ellis almost 2 years
I am using Hibernate as the ORM for a database that has a number of foreign key relationships. The problem is that sometimes I want to fetch these related datasets and sometimes I do not, so on these collections I have set "fetch" to "lazy". Unfortunately, every time I try to serialize these objects Hibernate will throw a LazyInitializationException, because the session is closed. Using an OpenSessionInView filter simply causes Hibernate to populate these collections anyway, thus defeating the whole purpose of having a lazy collection in the first place.
Is there a simple way to serialize or otherwise extract the data populated in the POJO without triggering the LIE, and without having to populate all of the lazy collections?
EDIT: Here is some example code I am trying to get working, dealing with two tables, "Departments" and "Employees," which is the child in a one-to-many relationship with Departments. I want to be able to view the Departments listed in the database, without having to load all of the Employees that belong to said Departments:
Departments:
package com.test.model; // Generated Apr 7, 2012 7:10:28 PM by Hibernate Tools 3.4.0.CR1 import java.util.HashSet; import java.util.Set; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import static javax.persistence.GenerationType.IDENTITY; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.Table; /** * Departments generated by hbm2java */ @Entity @Table(name="Departments" ,catalog="test" ) public class Departments implements java.io.Serializable { private Integer id; private String name; private Set<Employees> employeeses = new HashSet(0); public Departments() { } public Departments(String name) { this.name = name; } public Departments(String name, Set employeeses) { this.name = name; this.employeeses = employeeses; } @Id @GeneratedValue(strategy=IDENTITY) @Column(name="Id", unique=true, nullable=false) public Integer getId() { return this.id; } public void setId(Integer id) { this.id = id; } @Column(name="Name", nullable=false) public String getName() { return this.name; } public void setName(String name) { this.name = name; } @OneToMany(fetch=FetchType.LAZY, mappedBy="departments") public Set<Employees> getEmployeeses() { return this.employeeses; } public void setEmployeeses(Set employeeses) { this.employeeses = employeeses; } }
Employees:
package com.test.model; // Generated Apr 7, 2012 7:10:28 PM by Hibernate Tools 3.4.0.CR1 import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import static javax.persistence.GenerationType.IDENTITY; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; /** * Employees generated by hbm2java */ @Entity @Table(name="Employees" ,catalog="test" ) public class Employees implements java.io.Serializable { private Integer id; private Departments departments; private String firstName; private String lastName; public Employees() { } public Employees(Departments departments, String firstName, String lastName) { this.departments = departments; this.firstName = firstName; this.lastName = lastName; } @Id @GeneratedValue(strategy=IDENTITY) @Column(name="Id", unique=true, nullable=false) public Integer getId() { return this.id; } public void setId(Integer id) { this.id = id; } @ManyToOne(fetch=FetchType.LAZY) @JoinColumn(name="DepartmentsId", nullable=false) public Departments getDepartments() { return this.departments; } public void setDepartments(Departments departments) { this.departments = departments; } @Column(name="FirstName", nullable=false) public String getFirstName() { return this.firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } @Column(name="LastName", nullable=false) public String getLastName() { return this.lastName; } public void setLastName(String lastName) { this.lastName = lastName; } }
My action class (which gets serialized by the Struts2 XSLT result):
package com.test.view; import java.util.List; import java.util.Iterator; import com.opensymphony.xwork2.ActionSupport; import com.test.controller.DepartmentsManager; import com.test.model.Departments; import com.test.util.HibernateUtil; public class DepartmentsAction extends ActionSupport { private DepartmentsManager departmentsManager; private List<Departments> departmentsList; public DepartmentsAction() { this.departmentsManager = new DepartmentsManager(); } public String list() { this.departmentsList = departmentsManager.list(); System.out.println("Execute called"); HibernateUtil.createDTO(departmentsList); return SUCCESS; } public List<Departments> getDepartmentsList() { return departmentsList; } public void setDepartmentsList(List<Departments> departmentsList) { this.departmentsList = departmentsList; } }
My Manager class (which the Action class calls to populate the list of Departments):
package com.test.controller; import java.util.List; import java.util.Iterator; import org.hibernate.Criteria; import org.hibernate.Hibernate; import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.Session; import com.test.model.Departments; import com.test.util.HibernateUtil; public class DepartmentsManager { public List<Departments> list() { Session session = HibernateUtil.getSessionFactory().getCurrentSession(); session.beginTransaction(); List<Departments> set = null; try { Query q = session.createQuery("FROM Departments"); /*Query q = session.createQuery("FROM Departments d JOIN FETCH d.employeeses e");*/ q.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); set = (List<Departments>) q.list(); } catch (HibernateException e) { e.printStackTrace(); session.getTransaction().rollback(); } session.getTransaction().commit(); return set; } }