Ale*_*exz 8 java collections hibernate lazy-initialization
今天我遇到了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;
}
Run Code Online (Sandbox Code Playgroud)
方法initializeIssues:
public void initializeIssues(Period period) {
if (period.getIssues() != null) {
Hibernate.initialize(period.getIssues());
}
}
Run Code Online (Sandbox Code Playgroud)
如果收集期包含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)
Run Code Online (Sandbox Code Playgroud)
但是,如果我删除一些行并将方法更改为
@Transactional
public Period getDefault(Team team) {
Period defaultPeriod = team.getDefaultPeriod();
_periodDAO.initializeIssues(defaultPeriod);
return defaultPeriod;
}
Run Code Online (Sandbox Code Playgroud)
它工作正常.
我调试了第一个示例,并且hibernate会话在整个方法期间没有关闭.
据我所知,如果会话中的加载对象(句点中的一个元素)具有与活动会话关联的集合,并且在对象之前存在(defaultPeriod)也具有相同的关联 - 它(defaultPeriod)将失去其关联.
这是真的吗?还有谁遇到过同样的问题?
谢谢你的回答.
Sot*_*lis 13
据推测,你的Team论点来自另一个事务和另一个Hibernate Session.
当一个@Transactional方法返回时,TransactionManager关闭Session它会进行一些清理并取消设置(设置为null)Session所有PersistentCollection实例的字段.你defaultPeriod有其中一个在其issues领域.
Hibernate Hibernate.initialize()强制执行lazy的初始化PersistentCollection,但是有以下代码(调用AbstractPersistentCollection#forceInitialization())
if ( session == null ) {
throw new HibernateException( "collection is not associated with any session" );
}
Run Code Online (Sandbox Code Playgroud)
如果您计划在issues原始@Transactional方法(生成的代码Team)之外使用集合,则需要加载基础对象.将其更改为EAGER加载或执行您正在执行的操作Hibernate.initialize().
另一个解决方案是让Session最后一个长度超过第一个长度@Transactional,但我没有详细说明.快速google或SO搜索应该提出一些选择.
这就是正在发生的事情
Period defaultPeriod = team.getDefaultPeriod();
Run Code Online (Sandbox Code Playgroud)
获取一个Period带id 的对象(例如)42.因为它发生在另一个Session已经被关闭的时候,它issues是一个PersistentCollection有null Session参考的东西,并且会抛出Exception你得到的东西.
你这样做
List<Period> periods = _periodDAO.getPeriods(team);
Run Code Online (Sandbox Code Playgroud)
假设List包含一个Period带id 的对象42,所以ifin
if (!periods.contains(defaultPeriod)) {
defaultPeriod = periods.get(periods.size() - 1);
}
Run Code Online (Sandbox Code Playgroud)
没有被执行.尽管equals()回报率true(contains()也返回true并成为false因!),对象是不一样的.on中List有一个附加(非null)Session,因此可以初始化一个.但你的,defaultPeriod不能举办的那个.
| 归档时间: |
|
| 查看次数: |
19011 次 |
| 最近记录: |