[英]Hibernate lazy initialization - failed to lazily initialize a collection
[英]Lazy collection initialization fails in hibernate
今天我遇到了hibernate的下一個問題:
我的方法:
@Transactional
public Period getDefault(Team team) {
Period defaultPeriod = team.getDefaultPeriod();
List<Period> periods = _periodDAO.getPeriods(team);
if (!periods.contains(defaultPeriod)) {
defaultPeriod = periods.get(periods.size() - 1);
}
}
_periodDAO.initializeIssues(defaultPeriod);
return defaultPeriod;
}
方法initializeIssues:
public void initializeIssues(Period period) {
if (period.getIssues() != null) {
Hibernate.initialize(period.getIssues());
}
}
如果收集期包含defaultPeriod,我會收到異常
Caused by: org.hibernate.HibernateException: collection is not associated with any session
at org.hibernate.collection.AbstractPersistentCollection.forceInitialization(AbstractPersistentCollection.java:474)
at org.hibernate.Hibernate.initialize(Hibernate.java:417)
但是,如果我刪除一些行並將方法更改為
@Transactional
public Period getDefault(Team team) {
Period defaultPeriod = team.getDefaultPeriod();
_periodDAO.initializeIssues(defaultPeriod);
return defaultPeriod;
}
它工作正常。
我調試了第一個示例,並且hibernate會話在整個方法期間沒有關閉。
據我所知,如果會話中的加載對象( 句點中的一個元素)具有與活動會話關聯的集合,並且在對象之前存在( defaultPeriod )也具有相同的關聯 - 它( defaultPeriod )將失去其關聯。
這是真的嗎? 還有誰遇到過同樣的問題?
謝謝你的回答。
據推測,您的Team
參數來自另一個事務和另一個Hibernate Session
。
當@Transactional
方法返回時, TransactionManager
關閉Session
,它執行一些清理並取消設置(設置為null
)所有PersistentCollection
實例的Session
字段。 您的defaultPeriod
在其issues
字段中包含其中一個。
Hibernate的Hibernate.initialize()
強制執行惰性PersistentCollection
的初始化,但是具有以下代碼(調用AbstractPersistentCollection#forceInitialization()
)
if ( session == null ) {
throw new HibernateException( "collection is not associated with any session" );
}
如果您計划在原始@Transactional
方法(生成Team
的代碼)之外使用issues
集合,則需要加載基礎對象。 將其更改為EAGER加載或使用Hibernate.initialize()
執行您正在執行的操作。
另一個解決方案是使Session
持續時間長於第一個@Transactional
的長度,但我沒有詳細說明。 快速google或SO搜索應該提出一些選擇。
這就是正在發生的事情
Period defaultPeriod = team.getDefaultPeriod();
獲取具有id(例如) 42
的Period
對象。 因為它發生在另一個已經關閉的Session
中,所以issues
是PersistentCollection
,它有一個null
Session
引用,並且會拋出你得到的Exception
。
你這樣做
List<Period> periods = _periodDAO.getPeriods(team);
假設List
包含一個id為42
的Period
對象,所以if
in
if (!periods.contains(defaultPeriod)) {
defaultPeriod = periods.get(periods.size() - 1);
}
沒有被執行。 雖然equals()
返回true
( contains()
也返回true
並因為!
而變為false
),但對象不一樣。 List
的on有一個附加的(非null) Session
,因此可以初始化一個。 但是你的, defaultPeriod
持有的那個不能。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.