Hibernate: org.hibernate.LazyInitializationException: could not initialize proxy - no Session [duplicate]
Asked Answered
S

4

15

Have following query to the database:

        Session session = EmployeesDAO.getSessionFactory().getCurrentSession();
        List<Employee> employees = new ArrayList<Employee>();
        try {
            session.beginTransaction();
            String hqlQuery = "from Employee emp "
                    + "left join fetch emp.employeesOffices employeesOffice "
                    + "left join fetch employeesOffice.office employeesOfficeOffice "
                    + "left join fetch employeesOfficeOffice.company "
                    + "left join fetch emp.address empAddress "
                    + "left join fetch empAddress.city empAddressCity "
                    + "left join fetch empAddressCity.country";
            Query empQuery = session.createQuery(hqlQuery);
            empQuery.setMaxResults(maxResult);
            employees = (List<Employee>) empQuery.list();
            session.getTransaction().commit();

        } catch (HibernateException e) {
            session.getTransaction().rollback();
            e.printStackTrace();
        }

While fetching employee.address.street, employee.address.houseNumber or employee.address.city it fails with the exception:

org.hibernate.LazyInitializationException: could not initialize proxy - no Session
    at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:164)
    at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:285)
    at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)
    at com.employees.model.Address_$$_javassist_6.getCity(Address_$$_javassist_6.java)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at javax.el.BeanELResolver.getValue(BeanELResolver.java:87)
    at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:67)
    at org.apache.el.parser.AstValue.getValue(AstValue.java:169)
    at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:189)
    at org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate(PageContextImpl.java:985)
    at org.apache.jsp.WEB_002dINF.listEmployees_jsp._jspx_meth_c_005fout_005f3(listEmployees_jsp.java:306)
    at org.apache.jsp.WEB_002dINF.listEmployees_jsp._jspx_meth_c_005fforEach_005f1(listEmployees_jsp.java:248)
    at org.apache.jsp.WEB_002dINF.listEmployees_jsp._jspx_meth_c_005fforEach_005f0(listEmployees_jsp.java:155)
    at org.apache.jsp.WEB_002dINF.listEmployees_jsp._jspService(listEmployees_jsp.java:89)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:690)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:477)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:402)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:329)
    at com.employees.controller.EmployeeController.processRequest(EmployeeController.java:69)
    at com.employees.controller.EmployeeController.doGet(EmployeeController.java:30)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1001)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

Mapping for Employee:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.employees.model.Employee" table="employees">
        <id column="employee_id" name="employeeId" type="int">
            <generator class="sequence">
                <param name="sequence">EMP_SEQ</param>
            </generator>
        </id>
        <property column="first_name" name="firstName" type="java.lang.String" />
        <property column="last_name" name="lastName" type="java.lang.String" />

        <many-to-one name="address" column="address_id" 
            class="com.employees.model.Address"/>
        <set name="employeesOffices" >
            <key column="employee_id" />
            <one-to-many class="com.employees.model.EmployeeOffice"/>
        </set>

    </class>
</hibernate-mapping>

Mapping for Address:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.employees.model.Address" table="addresses">
        <id column="address_id" name="addressId" type="int">
            <generator class="sequence">
                <param name="sequence">ADDRESS_SEQ</param>
            </generator>
        </id>
        <property column="street" name="street" type="java.lang.String" />
        <property column="house_number" name="houseNumber" type="int" />
        <many-to-one name="city" column="city_id"
            class="com.employees.model.City"/>
    </class>

</hibernate-mapping>

It's absolutely normal with other classes (Office, Company, etc). If comment the lines which load address fields in jsp application works without any exceptions. What's wrong? By the way it shows all information on jsp despite the exception.

Snakemouth answered 26/1, 2013 at 22:17 Comment(1)
off topic: I think it's better to specify package attribute in hibernate-mapping tag, after that you have no need to write full name of classesBorries
C
37

Your objects inside employee are lazy initialized. That's mean, they are initializing only on demand on non-closed session. So you have to initialize them all manually inside loop after fetching from DB:

Query empQuery = session.createQuery(hqlQuery);
empQuery.setMaxResults(maxResult);
employees = (List<Employee>) empQuery.list();
for (Employee emp : employees) {
    Hibernate.initialize(emp.address);
}
Clodhopper answered 26/1, 2013 at 22:21 Comment(9)
Then what's the point of lazy? Might as well change the semantics to do an eager fetch.Rufescent
@Rufescent this is not always needed. Sometimes it is convenient to have lazy initialization, and initialize children only if it is needed.Clodhopper
that's right, that's why my suggestion is that you get the scoping semantics right for each case. :)Rufescent
Why are they lazy initialized? Why do Office and other associations work correctly? Is it wrong that left join fetch provides eager fetching?Snakemouth
for (Employee emp : employees) { Hibernate.initialize(emp.getAddress()); } gives me NullPointerException.Snakemouth
yes if you specify join fetch all data would be get immediately. look at this topic about fetch strategies mkyong.com/hibernate/hibernate-fetching-strategies-examplesBorries
The point here is that you want the mapping to be lazy by default. This gives you the opportunity to load the data if you know you need it but not if you don't. If you need the data you need the data, you can't get away from that! You can use a join fetch or just access the property before closing the session but either way, you need that data so make sure you load it!Leatherjacket
@Snakemouth add additionally check for null values: ... { if (emp != null) Hibernate.initialize(emp.getAddress()); } .... It this will not help, then post here full stack trace of this NPE exception.Clodhopper
Thanks a lot, @Alex and @Andremoniy! You really help me to understand and solve this problem! I'll update my question with the code.Snakemouth
F
16

Sinche Hibernate 4.2 you can use

.setProperty("hibernate.enable_lazy_load_no_trans", "true");

this option solves the dreaded

org.hibernate.LazyInitializationException: could not initialize proxy -
no Session

which took so many hours of life to programmers away.

Fabre answered 21/1, 2016 at 9:26 Comment(6)
Doesn't work for me in Hibernate 4.3.11.FinalPestle
This did the trick on Hibernate 5.0.11.FinalLailaibach
Worked for me - Hibernate 4.3.6 FinalProtomorphic
You might read this article before doing this.Shape
it's anti patternUntimely
@zond, It's the only solution that has worked with me, what else shall we do to overcome this problem?Peignoir
R
9

Has nothing to do with the mapping. When you provide for lazy loading on an object, you accept a responsibility that has bewitched the ORM world for a decade: that the session you loaded the object with will be the same one as the session that is present when the lazy requests are issued.

In your case, it looks like the session is completely gone.

You have to have some means of either maintaining the session (which often leads to a need for conversation scope, which would mean either Seam or CDI (in EE 6)) or you have to resync your object with the new session that you have (usually by looking it up again).

Rufescent answered 26/1, 2013 at 22:22 Comment(0)
B
2

add laze=false into <class name="com.employees.model.Employee" table="employees"> or you can init your object in Hibernate.init(Object) when you get object from db

Borries answered 26/1, 2013 at 22:36 Comment(5)
Thanks but lazy=false doesn't help. I answered about Hibernate.initialize under another answer. It doesn't work too.Snakemouth
oh. I make mistake. specify lazy=false in <class name="com.employees.model.Employee" table="employees">. This make all fields of Employee class not lazy inicializationBorries
Properties of all hibernate classes are not lazy by default, associations are loaded through left join fetch. Is it not right? I can't really see any lazy loaded attributes.Snakemouth
By default all properties lazy.Borries
but if you set lazy=false to all classes in your mapping it makes fetch join automaticlyBorries

© 2022 - 2024 — McMap. All rights reserved.