跨越请求的JSF + Hyperjaxb3 + Hibernate LazyInitializationException

时间:2010-09-24 13:47:36

标签: hibernate jpa lazy-loading trinidad hyperjaxb

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

场景是:

  1. 用户在组合框中进行选择
  2. 用户点击向服务器发送请求并返回到同一表单的控件
  3. 提交表单中的数据,并且组合框中的选择应该与用户在步骤1中的选择一样。在组合框项目(JPA对象)上调用equals()方法并抛出此异常:
  4. org.hibernate.LazyInitializationException:懒得初始化一个角色集合:package.AnObject.items,没有会话或会话被关闭          at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)      at org.hibernate.collection.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(...)。当该属性是一个列表时,它由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();
    }
    
    HyperJaxb生成的

    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转换为我的对象后调用了right equals()。

1 个答案:

答案 0 :(得分:1)

你得到这个是因为你的对象没有分离(1)而你在会话之外访问数据(2)(3)。要更正,您应该以任意组合解决(1-3)。

  1. 分离您的对象。这可能是最简单的,但它不是延迟加载。
  2. 确保会话可用。你说你正在使用OEMIV模式 - 当调用equals方法时会话是怎么回事?我相信这是因为在视图渲染期间不会调用equals,而是在其他一些JSF阶段调用equals。您可以尝试扩展OEMIV模式,使其跨越整个JSF生命周期。
  3. 不访问数据。建议使用equals(...)和hashCode(...)方法,但不是必需的。你可以在HJ3中禁用它们的生成,你可以从hashCode()/ equals(...)构建中排除某些属性,你可以使用自己的equals和hashCode策略 - 有很多方法可以实现这一点。
  4. 我个人,我先检查,为什么会议不在那里。