How to avoid LazyInitializationException in Hibernate?

12,696

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.

Share:
12,696
J Ellis
Author by

J Ellis

I am a software engineer and intellectual property attorney.

Updated on June 04, 2022

Comments

  • J Ellis
    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;
    }
    }