Note that there are some explanatory texts on larger screens.

plurals
  1. POLazyInitializationException on eagerly fetched (detached) collection
    primarykey
    data
    text
    <p>First some info:</p> <ul> <li>I'm using: <ul> <li>Spring 3.1.1.RELEASE</li> <li>Hibernate 4.1.5.SP1</li> <li>JSF 2.0?</li> <li>OpenSessionInViewFilter (org.springframework.orm.hibernate4.support.OpenSessionInViewFilter)</li> <li>PrimeFaces 3.3.1</li> <li>Lombok 0.11.2</li> <li>JBoss 7.1.1.Final</li> </ul></li> </ul> <p><strong>The short version:</strong></p> <p>When my entity <code>Emloyee</code> becomes detached (and thus it's eagerly fetched collection of <code>Location</code>s too), I cannot call <code>Employee.getLocations().add()</code> without getting a <code>LazyInitializationException</code>. Using a non-JPA based collection to act as a transfer object works.</p> <p><strong>The Long version:</strong></p> <p>I have an entity <code>Employee</code> that has a collection of <code>Location</code>s:</p> <pre><code>@Data @EqualsAndHashCode(callSuper = true, of = {}) @ToString(callSuper = true, of = {}) @Entity @Inheritance(strategy = InheritanceType.JOINED) public class Employee extends Person { @ManyToMany @JoinTable(name = "location_employee", joinColumns = @JoinColumn(name = "employee_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "location_id", referencedColumnName = "id")) private Set&lt;Location&gt; locations = new HashSet&lt;Location&gt;(); } </code></pre> <p><code>Employee</code> extends from <code>Person</code> which has some strings like name, etc. but these are not relevant.</p> <pre><code>@Data @EqualsAndHashCode(of = "id") @ToString(of = { "id", "name" }) @Entity @Inheritance(strategy = InheritanceType.JOINED) public class Person { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Setter(AccessLevel.NONE) private Long id; private String name; } </code></pre> <p>The <code>Location</code> class too is very simple:</p> <pre><code>@Data @EqualsAndHashCode(of = "id") @ToString(of = { "id", "name" }) @Entity public class Location { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Setter(AccessLevel.NONE) private Long id; private String name; @ManyToMany @JoinTable(name = "location_employee", joinColumns = @JoinColumn(name = "location_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "employee_id", referencedColumnName = "id")) private Set&lt;Employee&gt; employees = new HashSet&lt;Employee&gt;(); } </code></pre> <p>All collections are lazy by default. However in my JSF page I want to add <code>Location</code>s to an existing <code>Employee</code>. To do this I eager load my <code>Employee</code> using the following backing bean:</p> <pre><code>@Named @Scope("view") public class BackingBean { @Inject private EmployeeDAO employeeDAO; private Employee employeeFull; @Inject private LocationDAO locationDAO; private List&lt;Location&gt; locations; public Employee getSelectedEmployeeFull() { if (selectedEmployeeFull == null) { selectedEmployeeFull = employeeDAO.getEagerById(1L); } return selectedEmployeeFull; } public void setEmployeeFull(Employee e) { employeeFull = e; } public List&lt;Location&gt; getLocations() { if (locations == null) { locations = locationDAO.getAll() } return locations; } //... } </code></pre> <p>The <code>EmployeeDAO</code> class including the eager load query:</p> <pre><code>@Named public class EmployeeDAO { @Inject private SessionFactory sessionFactory; @Transactional(readOnly = true) public Employee getEager(Long id) { Query q = sessionFactory.getCurrentSession().createQuery("select e from Employee e join fetch e.locations where e.id = :id"); q.setParameter("id", id); try { return (Employee) q.uniqueResult(); } catch (NonUniqueObjectException ex) { //Exception logging/handling return null; } } } </code></pre> <p>In my JSF I have the following snippet:</p> <pre><code>&lt;p:dialog dynamic="true"&gt; &lt;h:form&gt; &lt;p:selectCheckboxMenu label="Locations" value="#{employeeBean.employeeFull.locations}"&gt; &lt;f:selectItems var="location" itemLabel="#{location.name}" value="#{employeeBean.locations}" /&gt; &lt;/p:selectCheckboxMenu&gt; &lt;p:commandButton value="save" action="#{employeeBean.update}"/&gt; &lt;/h:form&gt; &lt;/p:dialog&gt; </code></pre> <p>When I open the dialog it loads the <code>employeeFull</code> property fine, and fills the <code>selectCheckboxMenu</code> with <code>Location</code>s and marks the <code>Location</code>s the <code>Employee</code> already has.</p> <p>However when I click the save button (without changing anything) and the form gets submitted the <code>Employee.locations</code> collection trows a <code>LazyInitializationException</code>:</p> <pre><code>09:36:42,633 WARNING [javax.enterprise.resource.webcontainer.jsf.lifecycle] (http-localhost-127.0.0.1-8080-1) failed to lazily initialize a collection, no session or session was closed: org.hibernate.LazyInitializationException: failed to lazily initialize a collection, no session or session was closed at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:394) [hibernate-core-4.1.5.SP1.jar:4.1.5.SP1] at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:386) [hibernate-core-4.1.5.SP1.jar:4.1.5.SP1] at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:379) [hibernate-core-4.1.5.SP1.jar:4.1.5.SP1] at org.hibernate.collection.internal.PersistentSet.add(PersistentSet.java:206) [hibernate-core-4.1.5.SP1.jar:4.1.5.SP1] at com.sun.faces.renderkit.html_basic.MenuRenderer.convertSelectManyValuesForModel(MenuRenderer.java:382) [jsf-impl-2.1.7-jbossorg-2.jar:] at com.sun.faces.renderkit.html_basic.MenuRenderer.convertSelectManyValue(MenuRenderer.java:129) [jsf-impl-2.1.7-jbossorg-2.jar:] at com.sun.faces.renderkit.html_basic.MenuRenderer.getConvertedValue(MenuRenderer.java:315) [jsf-impl-2.1.7-jbossorg-2.jar:] at org.primefaces.component.selectcheckboxmenu.SelectCheckboxMenuRenderer.getConvertedValue(SelectCheckboxMenuRenderer.java:34) [primefaces-3.3.1.jar:] at javax.faces.component.UIInput.getConvertedValue(UIInput.java:1030) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at javax.faces.component.UIInput.validate(UIInput.java:960) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at javax.faces.component.UIInput.executeValidate(UIInput.java:1233) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at javax.faces.component.UIInput.processValidators(UIInput.java:698) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1214) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at javax.faces.component.UIForm.processValidators(UIForm.java:253) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1214) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at org.primefaces.component.dialog.Dialog.processValidators(Dialog.java:359) [primefaces-3.3.1.jar:] at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1214) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1172) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:76) [jsf-impl-2.1.7-jbossorg-2.jar:] at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) [jsf-impl-2.1.7-jbossorg-2.jar:] at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118) [jsf-impl-2.1.7-jbossorg-2.jar:] at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593) [jboss-jsf-api_2.1_spec-2.0.1.Final.jar:2.0.1.Final] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:329) [jbossweb-7.0.13.Final.jar:] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:] at org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:79) [primefaces-3.3.1.jar:] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280) [jbossweb-7.0.13.Final.jar:] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:322) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:116) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:150) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter.doFilter(DefaultLoginPageGeneratingFilter.java:91) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:182) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:184) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:155) [spring-security-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) [spring-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259) [spring-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280) [jbossweb-7.0.13.Final.jar:] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:] at org.springframework.orm.hibernate4.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:119) [spring-orm-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) [spring-web-3.1.1.RELEASE.jar:3.1.1.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:280) [jbossweb-7.0.13.Final.jar:] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:248) [jbossweb-7.0.13.Final.jar:] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:275) [jbossweb-7.0.13.Final.jar:] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:161) [jbossweb-7.0.13.Final.jar:] at org.jboss.as.web.security.SecurityContextAssociationValve.invoke(SecurityContextAssociationValve.java:153) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:155) [jbossweb-7.0.13.Final.jar:] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) [jbossweb-7.0.13.Final.jar:] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) [jbossweb-7.0.13.Final.jar:] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:368) [jbossweb-7.0.13.Final.jar:] at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:877) [jbossweb-7.0.13.Final.jar:] at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:671) [jbossweb-7.0.13.Final.jar:] at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:930) [jbossweb-7.0.13.Final.jar:] at java.lang.Thread.run(Thread.java:662) [rt.jar:1.6.0_31] </code></pre> <p>The <code>EmployeeBean.update</code> method is never called as the breakpoint set on it is never hit.</p> <p><strike>Now for the grand finale: How can I prevent this <code>LazyInitializationException</code>.</strike></p> <p><strong>EDIT</strong></p> <p>I have created a workaround, but this is probably not the best solution:</p> <p>In the JSF page:</p> <pre><code>&lt;p:dialog dynamic="true" onShow="loadSelectedEmployee()"&gt; &lt;h:form&gt; &lt;p:remoteCommand action="#{employeeBean.loadSelectedEmployee}" name="loadSelectedEmployee" update=":editEmployeeDialogContent" /&gt; &lt;/h:form&gt; &lt;p:outputPanel layout="block" id="editEmployeeDialogContent"&gt; &lt;h:form rendered="#{employeeBean.selectedEmployeeLoaded}"&gt; &lt;p:selectCheckboxMenu label="Locations" value="#{employeeBean.selectedEmployee.locations}"&gt; &lt;f:selectItems var="location" itemLabel="#{location.name}" value="#{employeeBean.locations}" /&gt; &lt;/p:selectCheckboxMenu&gt; &lt;p:commandButton value="save" action="#{employeeBean.update}"/&gt; &lt;/h:form&gt; &lt;/p:outputPanel&gt; &lt;/p:dialog&gt; </code></pre> <p>In the backing bean:</p> <pre><code>public void loadSelectedEmployee() { if (!selectedEmployeeLoaded) { selectedEmployee.setLocations(locationManager .getByEmployee(selectedEmployee)); selectedEmployee.setRoles(roleManager .getByEmployee(selectedEmployee)); selectedEmployeeLoaded = true; } } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload