繁体   English   中英

跨请求的JSF + Hyperjaxb3 + Hibernate LazyInitializationException

[英]JSF + Hyperjaxb3 + Hibernate LazyInitializationException accross requests

我有带有特立尼达组件和Hyperjaxb3生成的JAXB / JPA实体bean的JSF应用程序。 在UI中,我使用具有JPA对象作为值的特立尼达组合框组件。

该方案是:

  1. 用户在组合框中进行选择
  2. 用户单击将请求发送到服务器并返回到相同表单的控件
  3. 提交了来自表单的数据,并且在组合框中的选择应该与用户在步骤1中所做的相同。在组合框项目(JPA对象)上调用equals()方法,并抛出此异常:

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)

我从Spring使用OpenEntityManagerInViewFilter来获取延迟加载的对象-可以在一个请求中使用。

在HyperJAXB生成的级别上, equals()方法调用equals(Object object, EqualsBuilder equalsBuilder)方法,其中equalsBuilder.append(...)对象的每个属性调用equalsBuilder.append(...) 当该属性是一个列表时,它由PersistenBag代理,这就是我得到LazyInitializationException的地方。

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)生成的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...);
    ...
}

你们对解决这个问题有任何想法吗?

我尝试使用JSF转换器,并让SelectItem具有String值(不是对象),但是如果我记得正确,则在将String转换为我的对象后调用equals()。

之所以会这样,是因为对象没有分离(1),并且在会话(3)之外访问数据(2)。 要更正,您应该以任意组合方式解决(1-3)。

  1. 分离物体。 这可能是最简单的,但它不是延迟加载。
  2. 确保会话可用。 您说您正在使用OEMIV模式-当调用equals方法时,为什么会话不存在? 我相信这是因为equals不在视图渲染期间调用,而是在其他一些JSF阶段调用。 您可以尝试扩展OEMIV模式,以使其覆盖整个JSF生命周期。
  3. 不要访问数据。 建议使用equals(...)和hashCode(...)方法,但不是必需的。 您可以在HJ3中禁用它们的生成,可以从hashCode()/ equals(...)构建中排除某些属性,可以使用自己的equals和hashCode策略-实现此目的的多种方法。

我个人而言,我先检查一下,为什么会议不在那里。

暂无
暂无

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

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