2011-09-09 127 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) 

希望这有助于。