简体   繁体   English

跨请求的JSF + Hyperjaxb3 + Hibernate LazyInitializationException

[英]JSF + Hyperjaxb3 + Hibernate LazyInitializationException accross requests

I have JSF application with trinidad components and JAXB/JPA entity beans generated by Hyperjaxb3. 我有带有特立尼达组件和Hyperjaxb3生成的JAXB / JPA实体bean的JSF应用程序。 In the UI I use Trinidad combo box component that has JPA object as values. 在UI中,我使用具有JPA对象作为值的特立尼达组合框组件。

The scenario is: 该方案是:

  1. User make selection in combo box 用户在组合框中进行选择
  2. User clicks on a control that sends request to the server and is returned to the same form 用户单击将请求发送到服务器并返回到相同表单的控件
  3. Data from the form was submitted and selection in combo box should be as user did in the step 1. equals() method is called on combo box items (JPA objects) and this exception is thrown: 提交了来自表单的数据,并且在组合框中的选择应该与用户在步骤1中所做的相同。在组合框项目(JPA对象)上调用equals()方法,并抛出此异常:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: package.AnObject.items, no session or session was closed at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358) at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350) org.hibernate.LazyInitializationException:无法延迟初始化角色集合:package.AnObject.items,在org.hibernate.collection的org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)上没有关闭任何会话。 .AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)

 at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:97)

 at org.hibernate.collection.PersistentBag.size(PersistentBag.java:225)

 at org.jvnet.hyperjaxb3.item.AbstractItemList.size(AbstractItemList.java:51)

 at java.util.AbstractList$Itr.hasNext(Unknown Source)

 at org.jvnet.jaxb2_commons.lang.builder.JAXBEqualsBuilder.append(JAXBEqualsBuilder.java:57)

 at org.jvnet.jaxb2_commons.lang.builder.JAXBEqualsBuilder.append(JAXBEqualsBuilder.java:29)

 at package.AnObject.equals(AnObject.java:177)

 at org.jvnet.jaxb2_commons.lang.builder.JAXBEqualsBuilder.append(JAXBEqualsBuilder.java:34)

 at package.ParentObject.equals(ParentObject.java:532)

 at package.ParentObject.equals(ParentObject.java:551)

 at java.util.ArrayList.indexOf(Unknown Source)

 at org.apache.myfaces.trinidad.component.UIXSelectMany._destructiveCompareOutOfOrderLists(UIXSelectMany.java:179)

 at org.apache.myfaces.trinidad.component.UIXSelectMany.compareValues(UIXSelectMany.java:139)

 at org.apache.myfaces.trinidad.component.UIXEditableValue.validate(UIXEditableValue.java:180)

 at org.apache.myfaces.trinidad.component.UIXEditableValue._executeValidate(UIXEditableValue.java:503)

 at org.apache.myfaces.trinidad.component.UIXEditableValue.processValidators(UIXEditableValue.java:270)

 at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1058)

 at javax.faces.component.UIComponentBase.processValidators(UIComponentBase.java:1058)

I use OpenEntityManagerInViewFilter from Spring to get lazy loaded objects - that works in one request. 我从Spring使用OpenEntityManagerInViewFilter来获取延迟加载的对象-可以在一个请求中使用。

On the level of HyperJAXB generated object equals() method calls equals(Object object, EqualsBuilder equalsBuilder) method where equalsBuilder.append(...) is called on each attribute of that object. 在HyperJAXB生成的级别上, equals()方法调用equals(Object object, EqualsBuilder equalsBuilder)方法,其中equalsBuilder.append(...)对象的每个属性调用equalsBuilder.append(...) When that attribute is a list it is proxied by PersistenBag and that is the point where I get the LazyInitializationException. 当该属性是一个列表时,它由PersistenBag代理,这就是我得到LazyInitializationException的地方。

equals() method - generated by HyperJaxb: equals()方法-由HyperJaxb生成:

public boolean equals(Object object) {
    if (!(object instanceof ParentObject)) {
        return false;
    }
    if (this == object) {
        return true;
    }
    final EqualsBuilder equalsBuilder = new JAXBEqualsBuilder();
    equals(object, equalsBuilder);
    return equalsBuilder.isEquals();
}

equals(Object object, EqualsBuilder equalsBuilder) generated by HyperJaxb: equals(Object object, EqualsBuilder equalsBuilder)生成的equals(Object object, EqualsBuilder equalsBuilder)

public void equals(Object object, EqualsBuilder equalsBuilder) {
    if (!(object instanceof ParentObject)) {
        equalsBuilder.appendSuper(false);
        return ;
    }
    if (this == object) {
        return ;
    }
    final ParentObjectthat = ((ParentObject) object);
    // PersitentBag, LazyInitializationException is thrown here
    equalsBuilder.append(this.getAnObject(), that.getAnObject());
    equalsBuilder.append(this.get..., that.get...);
    ...
}

Do you guys have any ideas how fix this problem? 你们对解决这个问题有任何想法吗?

I tried to use JSF converter and have SelectItem with a String value (not object) but if I remember right equals() is called after String is converted to my object. 我尝试使用JSF转换器,并让SelectItem具有String值(不是对象),但是如果我记得正确,则在将String转换为我的对象后调用equals()。

You get this because your objects are not detached (1) and you access data (2) outside the session (3). 之所以会这样,是因为对象没有分离(1),并且在会话(3)之外访问数据(2)。 To correct, you should address (1-3) in any combination. 要更正,您应该以任意组合方式解决(1-3)。

  1. Detach your objects. 分离物体。 This is probably the easiest, but it's no lazy loading. 这可能是最简单的,但它不是延迟加载。
  2. Make sure the session is available. 确保会话可用。 You say you're using OEMIV pattern - how comes that the session isn't there when the equals method is called? 您说您正在使用OEMIV模式-当调用equals方法时,为什么会话不存在? I believe it's because equals is called not during the view rendering but in some other JSF phases. 我相信这是因为equals不在视图渲染期间调用,而是在其他一些JSF阶段调用。 You can try to extend the OEMIV pattern to make it span over the whole JSF lifecycle. 您可以尝试扩展OEMIV模式,以使其覆盖整个JSF生命周期。
  3. Don't access the data. 不要访问数据。 equals(...) and hashCode(...) methods are recommended, but not required. 建议使用equals(...)和hashCode(...)方法,但不是必需的。 You can disable their generation in HJ3, you can exclude certain properties from hashCode()/equals(...) building, you can use your own equals and hashCode strategies - plenty of ways to achieve this. 您可以在HJ3中禁用它们的生成,可以从hashCode()/ equals(...)构建中排除某些属性,可以使用自己的equals和hashCode策略-实现此目的的多种方法。

Me personally, I'd check first, why is the session not there. 我个人而言,我先检查一下,为什么会议不在那里。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM