2011-09-09 166 views
2

我有一個實體懶惰地初始化一個集合,我也已經將PropertyChangeSupport添加到該實體類。這裏的制定者如何看起來像設置:Hibernate延遲加載的集合和PropertyChangeSupport

public void setAskPrices(Set<AskPrice> askPrices) { 
    propertyChangeSupport.firePropertyChange(ASKPRICES_PROPERTY, this.askPrices, 
      this.askPrices = askPrices); 
} 

在我的代碼中一些其他的問題,我建立一個標準查詢,我希望它急切地獲取這個集合:

List<PriceRequest> pr = session.createCriteria(PriceRequest.class) 
         .setFetchMode("askPrices", FetchMode.JOIN) 
         .add(Restrictions.ilike("reqNum", "%" + reqNum + "%")).list(); 

當我運行上面的查詢,我在Hibernate中得到一個異常:

Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection, no session or session was closed 
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383) 
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375) 
at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:122) 
at org.hibernate.collection.PersistentSet.size(PersistentSet.java:162) 
at java.util.AbstractSet.equals(AbstractSet.java:75) 
at java.beans.PropertyChangeSupport.firePropertyChange(PropertyChangeSupport.java:273) 
at com.frc_agencies.model.persistent.PriceRequest.setAskPrices(PriceRequest.java:160) 

周圍挖掘後,我發現,在中的firePropertyChange()函數CAL ls oldValu.equals(newValue)。在我的情況下,newValue是新的持久集合。在某些點上的equals()函數調用的新集,後者又調用org.hibernate.collection.AbstractPersistentCollection.readSize(),它看起來像這樣大小():

protected boolean readSize() { 
    if (!initialized) { 
     if (cachedSize!=-1 && !hasQueuedOperations()) { 
      return true; 
     } 
     else { 
      throwLazyInitializationExceptionIfNotConnected(); 
      CollectionEntry entry = session.getPersistenceContext().getCollectionEntry(this); 
      CollectionPersister persister = entry.getLoadedPersister(); 
      if (persister.isExtraLazy()) { 
       if (hasQueuedOperations()) { 
        session.flush(); 
       } 
       cachedSize = persister.getSize(entry.getLoadedKey(), session); 
       return true; 
      } 
     } 
    } 
    read(); 
    return false; 
} 

異常被拋出時throwLazyInitializationExceptionIfNotConnected()。 它調用下面的方法:

/** 
* Is the collection currently connected to an open session? 
*/ 
private final boolean isConnectedToSession() { 
    return session!=null && 
      session.isOpen() && 
      session.getPersistenceContext().containsCollection(this); 
} 

它返回上session.getPersistenceContext假()containsCollection(本);。 因此,出於某種原因,此時持久性收集不是當前會話的一部分。

我決定做一個實驗。我刪除的標準查詢調用setFetchMode()調用和查詢調用返回後簡單,我叫:

Hibernate.initialize(pr.getAskPrices()); 

而且似乎做工精細!

但我不想一直調用Hibernate.initialize()。任何人都可以建議我可能做什麼使這個工作使用我原來的setFetchMode()調用?

謝謝。

編輯: 發佈有關映射

<set name="askPrices" table="ASK_PRICE" inverse="true" lazy="true" fetch="select" cascade="all-delete-orphan"> 
    <meta attribute="bound">ASKPRICES_PROPERTY</meta> 
    <key on-delete="cascade"> 
     <column name="REQ_ID" not-null="true" /> 
    </key> 
    <one-to-many class="AskPrice" /> 
</set> 
+0

請張貼您的映射XML(或註釋)。另外,看看這個錯誤報告。 https://hibernate.onjira.com/browse/HHH-3524 – zmf

+0

我發佈了相關映射。即使我沒有對實際關聯(僅限於父對象)添加任何限制,該錯誤似乎也是相關的。 – Caleb

回答

0

當您設置this.askprice = askprice,你做你的this.askprice沒有持久性,因此與會話下一條語句會拋出異常慵懶。您可以在Xml映射(lazy =「false」)中將懶惰更改爲false,這是我正在使用的一種不好的做法,或者可以嘗試使用Spring和Hibernatetemplate,這可以解決問題。

0

什麼工作對我來說是立即關閉設定成另一種類型的收藏:

List listOfObjects = new ArrayList(aMethod.getASetOfObjects()); 

我們使用Hibernate的舊版本卡住。所以我的猜測是Hibernate代碼中有一個錯誤。通過立即構建另一個Java Collection,它將對象複製到(非易失性)物理內存,而不是休眠緩存。

所以原來的問題就解決了喜歡的東西:

List this.askPrices = new ArrayList(askPrices) 

希望這有助於。