Problem mit org.hibernate.LazyInitializationException

bluer

Aktives Mitglied
Hi Leute,

ich bin hier echt am verzweifeln!!! Ich bearbeite gerade eine Webanwendung und mein Chef möchte gerne, dass so wenig Reloads wie möglich verwendet werden. Demzufolge versuche ich komplett mit Ajax-Events zu arbeiten. Es gibt eine Hauptseite bei der mit Hilfe von Tabs zwischen den Funktionen wie: Startseite, Projekte, Nutzerverwaltung,... navigiert werden kann. Das öffnen der einzelnen Tabs gibt noch keine Probleme, jedoch sobald ich einzelene Panele neu laden möchte, wirft er mir ständig beim Laden von Listen folgende Exception
Java:
org.hibernate.LazyInitializationException: : failed to lazily initialize a collection of role: model.consultant.Consultant.customers, no session or session was closed
Ein Codebeispiel:
Java:
private void initCustomerTree(){
        //this.root = new ProjectTreeRoot("");
        this.root = new TreeNodeImpl();
        if( this.loggedInUser == null)
            this.loggedInUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        //this.addNodes(null, root, loggedInUser);
        if( loggedInUser.getCustomer() == null){
            int counter = 1;
            for( Customer customer : loggedInUser.getConsultant().getCustomers()){
                TreeNodeImpl node = new TreeNodeImpl();
                node.setData(customer.getCompanyName());
                this.root.addChild(new Integer(counter), node);
                this.addNodes(Integer.toString(counter), node, customer.getUser());
                counter++;
            }
        }else{

        }
    }
Er lädt zwar den angemeldeten User, jedoch nicht die zugehörige Kundenliste oder die verknüpften Fragebögen. An deren Stelle steht bei der Debugger-Ansicht:
Java:
>Exception occurred in target VM: failed to lazily initialize a collection of role: model.consultant.Consultant.questionnaireRoots, no session or session was closed 
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: model.consultant.Consultant.questionnaireRoots, no session or session was closed
	at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383)
	at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375)
	at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:122)
	at org.hibernate.collection.PersistentBag.size(PersistentBag.java:248)
	at controller.project.ProjectController.initCustomerTree(ProjectController.java:93)
	at controller.project.ProjectController.getRoot(ProjectController.java:220)
	at controller.project.ProjectController$$FastClassByCGLIB$$6852000e.invoke(<generated>)
	at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
	at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:617)
	at controller.project.ProjectController$$EnhancerByCGLIB$$8302dcb0.getRoot(<generated>)
	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 javax.el.BeanELResolver.getValue(BeanELResolver.java:62)
	at javax.el.CompositeELResolver.getValue(CompositeELResolver.java:54)
	at com.sun.faces.el.FacesCompositeELResolver.getValue(FacesCompositeELResolver.java:72)
	at org.apache.el.parser.AstValue.getValue(AstValue.java:123)
	at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:186)
	at com.sun.facelets.el.TagValueExpression.getValue(TagValueExpression.java:71)
	at javax.faces.component.UIData.getValue(UIData.java:614)
	at org.ajax4jsf.component.UIDataAdaptorBase.getValue(UIDataAdaptorBase.java:1647)
	at org.richfaces.component.UITree.createDataModel(UITree.java:679)
	at org.ajax4jsf.component.UIDataAdaptorBase.getExtendedDataModel(UIDataAdaptorBase.java:621)
	at org.ajax4jsf.component.UIDataAdaptorBase.setRowKey(UIDataAdaptorBase.java:339)
	at org.richfaces.renderkit.TreeRendererBase.encodeAjaxChildren(TreeRendererBase.java:403)
	at org.ajax4jsf.component.UIDataAdaptorBase.encodeAjaxChild(UIDataAdaptorBase.java:454)
	at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxComponent(AjaxChildrenRenderer.java:146)
	at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxChildren(AjaxChildrenRenderer.java:83)
	at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxComponent(AjaxChildrenRenderer.java:157)
	at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxChildren(AjaxChildrenRenderer.java:83)
	at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxComponent(AjaxChildrenRenderer.java:157)
	at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxChildren(AjaxChildrenRenderer.java:83)
	at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxComponent(AjaxChildrenRenderer.java:157)
	at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxChildren(AjaxChildrenRenderer.java:83)
	at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxComponent(AjaxChildrenRenderer.java:157)
	at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxChildren(AjaxChildrenRenderer.java:83)
	at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxComponent(AjaxChildrenRenderer.java:157)
	at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxChildren(AjaxChildrenRenderer.java:83)
	at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxComponent(AjaxChildrenRenderer.java:157)
	at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxChildren(AjaxChildrenRenderer.java:83)
	at org.ajax4jsf.renderkit.AjaxChildrenRenderer.encodeAjaxComponent(AjaxChildrenRenderer.java:157)
	at org.ajax4jsf.renderkit.AjaxContainerRenderer.encodeAjax(AjaxContainerRenderer.java:124)
	at org.ajax4jsf.component.AjaxViewRoot.encodeAjax(AjaxViewRoot.java:685)
	at org.ajax4jsf.component.AjaxViewRoot.encodeChildren(AjaxViewRoot.java:556)
	at javax.faces.component.UIComponent.encodeAll(UIComponent.java:930)
	at com.sun.facelets.FaceletViewHandler.renderView(FaceletViewHandler.java:594)
	at org.ajax4jsf.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:100)
	at org.ajax4jsf.application.AjaxViewHandler.renderView(AjaxViewHandler.java:176)
	at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:110)
	at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
	at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:266)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.ajax4jsf.webapp.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:206)
	at org.ajax4jsf.webapp.BaseFilter.handleRequest(BaseFilter.java:290)
	at org.ajax4jsf.webapp.BaseFilter.processUploadsAndHandleRequest(BaseFilter.java:388)
	at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:515)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:368)
	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
	at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
	at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
	at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:35)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:187)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:169)
	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:113)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
	at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:859)
	at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:579)
	at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1555)
	at java.lang.Thread.run(Thread.java:619)
Nur versteh ich leider nicht warum???
Die Controller sind wie folgt annotiert:
Java:
@Scope(value = "session")
public class ProjectController implements ActionListener {
...
}
Ich habe leider keine Ahnung, wo ich bei der Lösung meines Problems überhaupt ansetzen soll?! Ich hoffe ihr könnt mir helfen.

Vieleb Dank schon einmal!!!
 
Habe gerade festgestellt, dass die Tabs einzeln funktionieren. D.h. wenn ich das Projecttab auskomentiere und nur das Nutzerverwaltnugstab laufwen lasse wird die Lazyexception nicht geworfen. Umgekehrt das gleiche Phänomen!!! Hilft das euch weiter, bei der Ursachenforschung?
 
Falls es weiterhilft, hier mal die Config-Dateien von meinem Vorgänger, die ich momentan verwende. Vllt liegt ja hier der Fehler:
spring-beans.xml:
[XML]<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
Index of /schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
Index of /schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
Index of /schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"
default-autowire="byType">

<context:annotation-config />

<!-- Configures the @Controller programming model -->
<mvc:annotation-driven />

<!-- Scans the classpath of this application for @Components -->
<context:component-scan base-package="controller" />
<context:component-scan base-package="service" />
<context:component-scan base-package="dao" />

<context😛roperty-placeholder location="classpath:META-INF/*.properties" />

<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="persistenceUnit" />
<property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<!-- <property name="showSql" value="true" />-->
<property name="generateDdl" value="true" />
<property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
</bean>
</property>
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<!-- Publishing session factory to be able view statistics -->
<bean id="sessionFactory" factory-bean="entityManagerFactory"
factory-method="getSessionFactory" />

<tx:annotation-driven proxy-target-class="true" />

<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/" />
<property name="suffix" value=".jsf" />
</bean>
</beans>
[/XML]
persistence.xml:
[XML]<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="persistenceUnit"
transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.connection.driver_class" value="org.hsqldb.jdbcDriver" />
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy" />
<property name="hibernate.connection.url" value="jdbc:mysql://localhost/develope" />
<property name="hibernate.connection.username" value="****" />
<property name="hibernate.connection.password" value="****" />
<!-- <property name="hibernate.hbm2ddl.auto" value="update" />-->

<property name="hibernate.connection.provider_class" value="org.hibernate.connection.C3P0ConnectionProvider" />
<property name="hibernate.c3p0.min_size" value="3" />
<property name="hibernate.c3p0.max_size" value="20" />
<property name="hibernate.c3p0.timeout" value="25200" /> <!-- less that mysql wait_timeout -->
<property name="hibernate.c3p0.max_statements" value="0" />
<property name="hibernate.c3p0.acquire_increment" value="3" />
<property name="hibernate.c3p0.idle_test_period" value="14400" />
<!-- <property name="hibernate.c3p0.validate" value="false" />-->
</properties>
</persistence-unit>
</persistence>[/XML]
 
was ist
> this.loggedInUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
?
ist irgendwas davon dein Code, deine Klassen, hast du selber unter Kontrolle wann ein User direkt aus der Datenbank geladen wird oder ähnliches?
dann könntest du an dieser Stelle direkt weitere Daten dazuladen, z.B. indem du sie dort in einer Schleife durchläufst wie später auch,
dabei werden sie gewiss initialisiert

versuche dies entweder direkt beim Laden oder ansonsten an möglichst früher Stelle wo erstmals mit dem User hantiert wird

-------

allgemein ist anscheinend irgendwann die zugehörige Session zu, die verwaltest du wohl nicht manuell von Anfang bis Ende?
dass es bei mehreren Tabs Probleme gibt klingt halbwegs passend, wenn jede davon (z.B. über den zugehörigen Request) mit einer eigenen Session versorgt wird, oder dieselbe Session geleert und User neu geladen wird oder wer weiß was,

richtig was zu sagen kann man dazu wohl kaum, ich jedenfalls nicht, allgemein gibts ja Unmengen zu diesem Thema,
allein der unvermeidbare Begriff OpenSessionInView,
aber ich kann da jetzt nichts konkretes vorschlagen, das ist was für Design der Gesamtanwendung,
hat da nicht jemand in der Firma mehr Gesamtüberblick?
 
Mit
Java:
this.loggedInUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
wird der aktuelle User in Erfahrung gebracht (also der, der angemeldet ist). Hierfür wird das Spring-Secrurity Framework verwendet. Ich verstehe leider nicht, warum er den Inhalt des Projekttabs lädt, wenn der Anwender sich im Usertab befindet und dort arbeitet?

Ich habe an jedem Controller für die einzelnen Tabs eine Session-Annotation. Ist dies dder falsche Weg?

Vielen dank schon einmal für diene Hilfe!!!
 
Lazy Loading ist ein Feature von ORM, bei dem man versucht, möglichst wenig aus der Datenbank zu laden, das man am Ende vielleicht garnicht braucht. Es wird hauptsächlich bei 1:n oder m:n Beziehungen benutzt, wo die geladenen Entities am Ende in einer Collection (Stet/List etc.) landen.

So wie es aussieht lädtst Du mit einer Hibernate-Session Deinen User. Die Listen seiner Fragebögen und Kunden sind lazy loaded. D.h. zu diesem Zeitpunkt stehen da noch garnicht die echten Daten drinnen. Jetzt schließt Du Deine Hibernate-Session und bringst den User zur Anzeige.
Jetzt rufst Du per AJAX die Tabs auf, um die Listen anzeigen zu lassen. Diese müssten jetzt aus der Datenbank geholt werden. Da Du aber keine Session offen hast, fliegt die Exception.
Dafür gibt es drei mögliche Lösungen:
1. Schalte in deinem Mapping das lazy loading ab. Dann werden die Daten immer sofort vollständig geladen. Geht aber bei größeren Listen zu lasten der Performance.
2. Sorge dafür, dass Du auch bei der Behandlung Deiner AJAX-Requests eine Session offen hast und sie direkt nach dem Laden wieder schließt. Das nennt sich Open-Session-in-View-Pattern.
3. Benutze eine langlebige Session, die solange offen bleibt, wie der Anwender sich mit Usern beschäftigt.

Die meiner Meinung nach sauberste Lösung ist Nummer 2.
 
es gibt auch noch 4. nillehammer 😉

4. Nutze Fetch Joins um beim laden des Objektes gleich die Abhängigkeit mitzuladen (sowas wie dyn. eager loading), Vorraussetzung: Man muss seine Use Cases kennen, also wissen, wann was mitgeladen werden soll.
 
Interessant. Hab ich noch nie benutzt (Glaub ich jedenfalls). Bei meinen Mappings habe ich immer FetchType.LAZY mit FetchMode.JOIN. Aber in den Queries gebe ich sonst nichts weiter an.
 
Ich habe den OpenSessionInViewFilter in der web.xml wie folgt eingebaut:
[XML]
...
<filter>
<filter-name>openSessionInViewFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>openSessionInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
...[/XML] und den FetchType auf Eager gesetzt. Hat beides leider nicht zur Lösung des Problems geführt. Habe mein Problem nun wie folgt gelöst:+
Java:
...
if( this.loggedInUser == null){
            User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            try{
                this.loggedInUser = userDao.findByName(user.getUsername());
            }catch(Exception e){
                System.out.println(e.getMessage());
            }
        }
..
Ist zwar doppelt gemoppelt, aber es funktioniert. Also er holt sich zuerst den anmeldeten User und lädt ihn anschließend aus der Datenbank nach. Die Variable user hat noch die LazyExceptions bei questionnaireRoots und Customers, jedoch der loggedInUser nicht mehr und somit bekomme ich die gewünschten Daten.

Mich beschäftigt nun aber doch noch eine Frage: Warum lädt er den Inhalt des Projekttabs, wenn der User sich im Nutzerverwaltungstzab befindet und dort arbeitet?
 
Hallo, das Problem scheint bei dir zu sein, dass sich dein Objekt im Modus detached befindet, d.h. nicht mehr an den EntiyManager gebunden ist.

Wenn du aber mit Hibernate Lazy-loading, machen willst muss sich das Objekt zum Zeitpunkt des Zugriffs im Modus persistent befinden, also am EntityManager gebunden sein.
 

Neue Themen


Zurück
Oben