web-dev-qa-db-fra.com

Hibernate: org.hibernate.LazyInitializationException: impossible d'initialiser le proxy - pas de session

Avoir la requête suivante dans la base de données:

        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();
        }

Lors de la récupération de employee.address.street, employee.address.houseNumber ou employee.address.city, il échoue à l'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)

Cartographie pour l'employé:

<?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>

Mappage pour l'adresse:

<?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>

C'est tout à fait normal avec d'autres classes (Office, Entreprise, etc.). Si vous commentez, les lignes qui chargent les champs d'adresse dans l'application jsp fonctionnent sans aucune exception. Qu'est-ce qui ne va pas? Au fait, il affiche toutes les informations sur jsp malgré l'exception.

11
tiktak

Vos objets à l'intérieur de employee sont lazy initialisés. C'est-à-dire qu'ils initialisent uniquement à la demande en session non fermée. Vous devez donc les initialiser tous manuellement dans la boucle après avoir récupéré de la base de données:

Query empQuery = session.createQuery(hqlQuery);
empQuery.setMaxResults(maxResult);
employees = (List<Employee>) empQuery.list();
for (Employee emp : employees) {
    Hibernate.initialize(emp.address);
}
35
Andremoniy

Sinche Hibernate 4.2 que vous pouvez utiliser

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

cette option résout le redouté

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

ce qui a pris tant d'heures de vie aux programmeurs.

15
saimiris_devel

N'a rien à voir avec la cartographie. Lorsque vous prévoyez un chargement paresseux sur un objet, vous acceptez une responsabilité qui a ensorcelé le monde ORM pendant une décennie: que la session avec laquelle vous avez chargé l'objet sera la même que la session qui est présente lorsque les demandes paresseuses sont émises.

Dans votre cas, il semble que la session soit complètement terminée.

Vous devez avoir un moyen de maintenir la session (ce qui conduit souvent à un besoin de portée de conversation, ce qui signifierait Seam ou CDI (dans EE 6)) ou vous devez resynchroniser votre objet avec la nouvelle session que vous avez ( généralement en le regardant à nouveau).

8
Rob

ajouter laze=false en <class name="com.employees.model.Employee" table="employees"> ou vous pouvez initier votre objet dans Hibernate.init (Object) lorsque vous obtenez un objet de db

2
Aleksei Bulgak