[英]Which Hibernate FetchMode will cause collections to be lazy-loaded?
[英]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.