@ManyToMany上的LazyInitializationException,尽管FetchType = EAGER

时间:2018-01-22 11:33:13

标签: hibernate jpa many-to-many jsf-2.2

由于我仍然面临这个问题,在梳理了这个流行异常的所有解决方案之后,我的情况就是这样。在我的情况下(汽车游泳池),我有这两个模型:

@Entity
public abstract class Car {
    @GeneratedValue @Id
    private Long id;
    private String name;
    @ManyToMany (cascade = {CascadeType.ALL},  fetch = FetchType.EAGER) 
    @JoinTable  (name = "Car_Person", joinColumns=@JoinColumn(name = "CarId", referencedColumnName = "id"), 
             inverseJoinColumns=@JoinColumn(name = "personId", referencedColumnName = "id"))
    private List<Person> carUsers; 
    //rest omitted
}

@Entity
public class Person {
    @GeneratedValue @Id
    private Long id;
    private String name;
    private int age;
        @ManyToMany(mappedBy = "carUsers", fetch = FetchType.EAGER)
        private List<Car> cars = new ArrayList<Car>();        
        //rest omitted
}

当我在我的JSF页面中引用Car时,我甚至得到了一个带有FetchType = Fetch.EAGER的LazyInitializationException:

<p:selectManyMenu value="#{carController.currentCar.carUsers}" converter="personConverter">     
    <f:selectItems value="#{personBean.persons}" var="person" itemLabel="#{person.name}" itemValue="#{person}"/>        
</p:selectManyMenu>

其中currentCar是Car的子类。

我认为,这里不需要查询,因为JPA正在自行解决m:n关系,对吗?

无论如何,我得到了这个堆栈跟踪:

11:02:27,769 SEVERE [javax.enterprise.resource.webcontainer.jsf.context] (default task-42) org.hibernate.LazyInitializationException: failed to lazily initialize a collection, could not initialize proxy - no Session
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:587)
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:204)
    at org.hibernate.collection.internal.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:148)
    at org.hibernate.collection.internal.PersistentBag.isEmpty(PersistentBag.java:266)
    at javax.faces.component.UIInput.isEmpty(UIInput.java:1272)
    at javax.faces.component.UIInput.validateValue(UIInput.java:1159)
    at javax.faces.component.UISelectMany.validateValue(UISelectMany.java:579)
    at javax.faces.component.UIInput.validate(UIInput.java:982)
    at javax.faces.component.UIInput.executeValidate(UIInput.java:1248)
    at javax.faces.component.UIInput.processValidators(UIInput.java:712)
    at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1261)
    at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1261)
    at org.primefaces.component.dialog.Dialog.processValidators(Dialog.java:423)
    at javax.faces.component.UIForm.processValidators(UIForm.java:253)
    at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1261)
    at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1261)
    at javax.faces.component.UIViewRoot.processValidators(UIViewRoot.java:1195)
    at com.sun.faces.lifecycle.ProcessValidationsPhase.execute(ProcessValidationsPhase.java:76)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:198)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:658)
    at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85)
    at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
    at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
    at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:131)
    at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
    at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
    at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
    at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
    at io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
    at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
    at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:292)
    at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:81)
    at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:138)
    at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:135)
    at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
    at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
    at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44)
    at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44)
    at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44)
    at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44)
    at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44)
    at io.undertow.servlet.api.LegacyThreadSetupActionWrapper$1.call(LegacyThreadSetupActionWrapper.java:44)
    at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:272)
    at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
    at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:104)
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:202)
    at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:805)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

任何帮助都将受到高度赞赏。

2 个答案:

答案 0 :(得分:0)

根据您的配置,您应该在web.xml中以Filter的身份尝试加载延迟属性。

Hibernate(注意你的spring和hibernate版本使用正确版本的org.springframework.orm.hibernate{***YOUR_VERSION***}):

<filter>
      <filter-name>hibernateFilter</filter-name>
      <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
      <init-param>
         <param-name>sessionFactoryBeanName</param-name>
         <param-value>sessionFactory</param-value>
      </init-param>     
   </filter>
   <filter-mapping>
     <filter-name>hibernateFilter</filter-name>
    <url-pattern>/*</url-pattern>

JPA:

<filter>
    <filter-name>oemInViewFilter</filter-name>
    <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
    <init-param>
        <param-name>entityManagerFactoryBeanName</param-name>
        <param-value>entityManagerFactory</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>oemInViewFilter</filter-name>
    <url-pattern>/*</url-pattern>

答案 1 :(得分:0)

好的,我找到了答案here。感谢伟大的BalusC。

问题不仅与多对多关系有关,这就是为什么EAGER获取没有帮助甚至反模式的原因(hibernate.enable_lazy_load_no_trans,Open Session in View)

问题的真正原因是SelectManyMenu。你必须告诉它,它应该处理什么样的结果集。在我的情况下,我必须像这样添加 collectionType

<p:selectManyMenu value="#carController.currentCar.motUsers}" collectionType="java.util.LinkedHashSet">