簡體   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