簡體   English   中英

Hibernate延遲加載的集合和PropertyChangeSupport

[英]Hibernate lazy-loaded collections and PropertyChangeSupport

我有一個懶惰地初始化Set的實體,並且還向該實體類添加了PropertyChangeSupport。 這是Set的二傳手的樣子:

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

在代碼的其他地方,我建立了一個Criteria查詢,並希望它熱切地獲取此集合:

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()函數調用oldValu.equals(newValue)。 就我而言,newValue是新的持久化Set。 有時equals()函數在新Set上調用size(),后者又調用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(this)上返回false。 因此由於某種原因,在這一點上,持久性收集不屬於當前會話。

我決定做一個實驗。 我刪除了Criteria查詢上的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>

對我有用的是立即將集合變成另一種類型的Collection:

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

我們被困使用較舊版本的Hibernate。 所以我的猜測是Hibernate代碼中有錯誤。 通過立即構造另一個java集合,它將對象復制到(非易失性)物理內存,而不是休眠緩存。

因此,原始問題將解決為:

    List this.askPrices = new ArrayList(askPrices)

希望這可以幫助。

當您設置this.askprice = askprice時,您使this.askprice不是持久性的,因此帶有session的下一條語句將引發惰性異常。 您可以在Xml映射中將lazy更改為false(lazy =“ false”),這是我正在使用的不良做法,或者可以嘗試使用Spring和Hibernatetemplate,這可能會解決問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM