Showing posts with label JPA. Show all posts
Showing posts with label JPA. Show all posts

Monday, September 7, 2026

Understanding & Fixing org.hibernate.LazyInitializationException in Java & Spring

I have faced this issue during my project development when I was trying to fix few testing issue. As per the scenario a one-to-many relation from VoiceServiceFileUpload class to VoiceServiceRequest class. When I want to load the VoiceServiceRequests that belongs to a voiceServiceFileUpload , I got this error. 

It seems that the error is caused by Hibernate lazily loading the VoiceServiceRequest  collection i.e. it returns a list of VoiceServiceRequest Id's only to the view. When the view tries to display the data, the session has been closed and hence, the error. Because , by default the FetchType is lazy true. After subsequent investigation and debug , I fix this by using below possible ways.


Error Log :-

ERROR, a7e3d058-4b9a-494a-87a4-08718d397b09: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: au.com.biz.service.sdp.bizservice.vmprovision.scheduler.domain.model.VoiceServiceFileUpload.VoiceServiceRequests, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: au.com.biz.service.sdp.bizservice.vmprovision.scheduler.domain.model.VoiceServiceFileUpload.VoiceServiceRequests, no session or session was closed
        at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
        at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
        at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:343)
        at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:86)
        at org.hibernate.collection.PersistentSet.hashCode(PersistentSet.java:411)
        at java.util.HashMap.getEntry(HashMap.java:424)
        at java.util.HashMap.containsKey(HashMap.java:415)
        at java.util.HashSet.contains(HashSet.java:184)
        at org.apache.commons.lang.builder.ToStringStyle.isRegistered(ToStringStyle.java:137)
        at org.apache.commons.lang.builder.ToStringStyle.appendInternal(ToStringStyle.java:421)
        at org.apache.commons.lang.builder.ToStringStyle.append(ToStringStyle.java:395)
        at org.apache.commons.lang.builder.ToStringBuilder.append(ToStringBuilder.java:840)
        at au.com.biz.service.sdp.bizservice.vmprovision.scheduler.domain.model.VoiceServiceFileUpload.toString(VoiceServiceFileUpload.java:68)
        at java.lang.String.valueOf(String.java:2826)
        at java.lang.StringBuffer.append(StringBuffer.java:219)
        at org.apache.commons.lang.builder.ToStringStyle.appendDetail(ToStringStyle.java:545)
        at org.apache.commons.lang.builder.ToStringStyle.appendInternal(ToStringStyle.java:509)
        at org.apache.commons.lang.builder.ToStringStyle.append(ToStringStyle.java:395)
        at org.apache.commons.lang.builder.ToStringBuilder.append(ToStringBuilder.java:840)
        at au.com.biz.service.sdp.bizservice.vmprovision.scheduler.domain.model.VoiceServiceRequest.toString(VoiceServiceRequest.java:106)
        at au.com.biz.service.sdp.bizservice.vmprovision.scheduler.domain.dao.hibernate.HibernateVoiceServiceRequestDao.update(HibernateVoiceServiceRequestDao.java:113)
        at au.com.biz.service.sdp.bizservice.vmprovision.scheduler.facade.spring.SpringVoiceServiceBatchJobFacade.updateRequestProvisionSendDate(SpringVoiceServiceBatchJobFacade.java:180)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:310)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
        at com.sun.proxy.$Proxy548.updateRequestProvisionSendDate(Unknown Source)
        at au.com.biz.service.sdp.infraservice.scheduler.application.job.VMProvisionBatchJob.executeJob(VMProvisionBatchJob.java:183)
        at au.com.biz.service.core.scheduler.SchedulerJob.executeTrigger(SchedulerJob.java:129)
        at au.com.biz.service.core.scheduler.SchedulerJob.execute(SchedulerJob.java:76)
        at org.quartz.core.JobRunShell.run(JobRunShell.java:203)
        at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:520)


Below the sample configuration for the entity.There is the context configuration , which is missing in this post.The configuration is configured as lazy loading true.


VoiceServiceFileUpload Entity :-

package javadevelopersguide.lab;
import java.util.HashSet;import java.util.Set;
import javax.persistence.CascadeType;import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.Id;import javax.persistence.OneToMany;import javax.persistence.Table;
@Entity@Table(name="voiceservicefileupload")public class VoiceServiceFileUpload{
@Id @Column(name="FILE_ID") private int FILE_ID; @Column(name="fileName") private String fileName; @OneToMany(cascade = CascadeType.ALL, mappedBy = "voiceServiceFileUpload") private Set<VoiceServiceRequest> VoiceServiceRequests= new HashSet<VoiceServiceRequest>(0); /** * Setter and Getter Method below */}

VoiceServiceRequest Entity :-

package jdevelopersguide.lab;
import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.FetchType;import javax.persistence.Id;import javax.persistence.JoinColumn;import javax.persistence.ManyToOne;import javax.persistence.Table;

@Entity@Table(name="voiceservicerequest")public class VoiceServiceRequest{
@Id @Column private int ID; @Column(name="serivcename") private String serviceName; @ManyToOne(fetch = FetchType.EAGER, optional = true) @JoinColumn(name = "FILE_ID", nullable = true) private VoiceServiceFileUpload voiceServiceFileUpload; /** * Setter and Getter Method below */
}

Option 1 -

You can use OpenEntityManagerInViewFilter to open your session in view mode. So, you need to configure this in your web.xml file. But, I didn't do this :) . Because I had few more limitation as per my project structure and architecture. 

Add the below code snippet into your web.xml
----------------------------------------------------------

<filter><filter-name>OpenEntityManagerInViewFilter</filter-name><filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class></filter><filter-mapping><filter-name>OpenEntityManagerInViewFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>


Option 2 -

This issue is happening the ,because the session has closed before you load the collection.So, you can open a new session, but its not suggested.So, I didn't do this :)

After google almost few articles , I found you can also try @Transactional for that method.Because,it makes your session active. But, I didn't try this. But , you can try your luck :)



Option 3 -

Finally , I have configured the VoiceServiceFileUpload to load eager (i.e fetch = FetchType.EAGER) and it resolved my issue.

Working fix :-

@OneToMany(cascade = CascadeType.ALL, mappedBy = "voiceServiceFileUpload",fetch = FetchType.EAGER) private Set<VoiceServiceRequest> VoiceServiceRequests= new HashSet<VoiceServiceRequest>(0);


Sunday, September 14, 2014

Hibernate Many-to-One Relationship Example Using Annotations

As we all know Hibernate is an easy and fast framework for work with any Database using Java language. This example show how to work with Many-To-One relationship in Hibernate.


I have used MySQL as database (Download Here) and Hibernate 3 jar files (Download Here). Also for applying Many-To-One relation we have used annotation. Even you can do this by using .xml config also, but that's too old and no one is using that now-a-days.

Create table department and employee :-

 Table department :
CREATE TABLE `department` (
  `deptid` int(11) NOT NULL,
  `deptname` varchar(100) default NULL,
  PRIMARY KEY  (`deptid`)
) ENGINE=InnoDB DEFAULT CHARSET=big5;


Table employee :
CREATE TABLE `employee` (
  `empid` int(11) NOT NULL,
  `empname` varchar(50) default NULL,
  `deptno` int(11) default NULL,
  PRIMARY KEY  (`empid`),
  KEY `deptno` (`deptno`),
  CONSTRAINT `employee_ibfk_1` FOREIGN KEY (`deptno`) REFERENCES `department` (`deptid`)
) ENGINE=InnoDB DEFAULT CHARSET=big5;
In this above both table , many employee could be from one department and implements Many-to-One relationship.


hibernate.cnf.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
   <session-factory>
        <!-- Adding mysql dialect -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
           <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <!-- Here jdeveloperguidedb is the database name -->
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/jdeveloperguidedb</property>
           <property name="hibernate.connection.username">root</property>
           <property name="hibernate.connection.password">root</property>
           <!-- show_sql property will help you to show the generated hibernate query on console -->          
           <property name="show_sql" >true</property> 
           <!-- Mapping entity class to hibernate -->
           <mapping class="com.jdeveloperguide.lab.Employee"></mapping> 
           <mapping class="com.jdeveloperguide.lab.Department"></mapping> 
    </session-factory>
</hibernate-configuration>

In this hibernate.cnf.xml file we have configure the initial setup for db , and it will help us to interact with db using hibernate.

Department.java

package com.jdeveloperguide.lab;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="department")
public class Department {

    @Id
    @Column(name="deptid")
    private int deptid;
   
    private String deptname;
   
    public int getDeptid() {
        return deptid;
    }
    public void setDeptid(int deptid) {
        this.deptid = deptid;
    }
    public String getDeptname() {
        return deptname;
    }
    public void setDeptname(String deptname) {
        this.deptname = deptname;
    }
}
Here Department.java is the entity class which we are going to persist or save into db.We have used few annotation here like @Entity ,@Table , @Id , @Column , etc. This entity class looks like a helper class.

@Entity - This annotation will help you to define entity in RDBMS.

@Table - This annotation will help you to define a database table (entity) by specifying name.

 i.e. @Table(name="department").

@Id - This annotation will help you to define the id column , it means the primary key.

@Column - This annotation will help you to define the column name by specifying the column name. If your column name and java variable name are different the you can specify by name. In this example our database column name and variable name are same so, not required specify the column name. Hibernate will automatically match and take care this. But I have used because for better understanding.




Employee.java

package com.jdeveloperguide.lab;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name="employee")
public class Employee {

@Id   
@Column(name="empid")
private int empid;

@Column(name="empname")
private String empname;

@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="deptno")
private Department dept;

public int getEmpid() {
    return empid;
}

public void setEmpid(int empid) {
    this.empid = empid;
}

public String getEmpname() {
    return empname;
}

public void setEmpname(String empname) {
    this.empname = empname;
}

public Department getDept() {
    return dept;
}

public void setDept(Department dept) {
    this.dept = dept;
}   
}


 Here Employee.java is the entity class which we are going to persist or save into db along with Department.We have used few more new annotations here like @ManyToOne , @JoinColumn, etc.
Here we have mapped many-to-one , means many employee from one department.

@ManyToOne - Mapping many-to-one relation with hibernate.

@JoinColumn - This annotation is used for map the reference foreign key for any entity. This indicates the association with entity/table.

 CreateSessionFactory.java

package com.jdeveloperguide.lab;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;

public class CreateSessionFactory {
    //Single point of access for SessionFactory
    private static final SessionFactory sessionFactory;
    static {
        try {
            //create sesson factory using the config file
            sessionFactory = new AnnotationConfiguration().configure("hibernate.cnf.xml").buildSessionFactory();
        } catch (Throwable ex) {
            throw new ExceptionInInitializerError(ex);
        }
    }
   
    //Static method for exposing the session
    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}

This class will help to create the SessionFactory object using .xml config file. This class having static method with we can call from any part of this application for getting SessionFactory object.Because , we will create Session object from SessionFactory

MainClass.java

package com.jdeveloperguide.lab;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;


public class MainClass {

    /**
     * @param args
     */
    public static void main(String[] args)throws Exception {
        MainClass mainObject=new MainClass();;
        Employee employee=new Employee();
        Department department=new Department();
        department.setDeptid(7);
        department.setDeptname("Computer Science");
       
        employee.setDept(department);
        employee.setEmpid(8);
        employee.setEmpname("Mr. JDeveloper");
        mainObject.saveEmployee(employee);
    }
   
    public void saveEmployee(Employee employee)throws Exception{
        Transaction transaction=null;
        Session session=null;
       
        try{
        //Create and open session
        session = CreateSessionFactory.getSessionFactory().openSession();
        //Create Transaction for maintain a user session
        transaction=session.beginTransaction();
        //Save the employee
        //Also it will save department ,because we have used cascade=CascadeType.ALL in employee
        session.save(employee);
        transaction.commit();
        }catch(HibernateException hibernateException){
            transaction.rollback();
            System.out.println("Error during save into DB :::"+hibernateException);
        }finally{
            session.close();
        }
    }
}

 This MainClass.java is the starting point of this example. Here we will execute our hibernate Many-to-One example and it will persist the data into DB.

Hibernate Generated SQL :-

Hibernate: select department_.deptid, department_.deptname as deptname1_ from department department_ where department_.deptid=?
Hibernate: insert into department (deptname, deptid) values (?, ?)
Hibernate: insert into employee (empname, deptno, empid) values (?, ?, ?)
When we will execute the MainClass.java class , it will generate these above queries by hibernate and these are auto generated. Its generating and showing because, we have mentioned in .xml config file show_sql is true.


Result in DB :-

Department Table











Employee Table