Java hibernate中的惰性集合初始化失败
今天我在hibernate中遇到了下一个问题: 我的方法:Java hibernate中的惰性集合初始化失败,java,hibernate,collections,lazy-initialization,Java,Hibernate,Collections,Lazy Initialization,今天我在hibernate中遇到了下一个问题: 我的方法: @Transactional public Period getDefault(Team team) { Period defaultPeriod = team.getDefaultPeriod(); List<Period> periods = _periodDAO.getPeriods(team); if (!periods.contains(defaultPeriod)) {
@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;
}
如果集合periods包含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)也具有相同的关联,则(defaultPeriod)将失去其关联
这是真的吗?还有谁面临同样的问题
谢谢您的回答。您的
团队
参数可能来自另一个事务和另一个Hibernate会话
当@Transactional
方法返回时,TransactionManager
关闭执行一些清理的会话
,并取消(设置为null
)所有PersistentCollection
实例的会话
字段。您的defaultPeriod
在其issues
字段中有一个
Hibernate的Hibernate.initialize()
强制初始化惰性的PersistentCollection
,但有以下代码(调用AbstractPersistentCollection#forceInitialization()
)
如果计划在原始@Transactional
方法(生成团队
的代码)之外使用问题
集合,则需要加载底层对象。将其更改为“快速加载”,或者使用Hibernate.initialize()
执行您正在执行的操作
另一个解决方案是使会话的持续时间长于第一个@Transactional
会话的持续时间,但我没有这方面的详细信息。快速的谷歌搜索应该会带来一些选择
这就是正在发生的事情
Period defaultPeriod = team.getDefaultPeriod();
获取id为(例如)的期间对象42
。因为它发生在另一个已关闭的会话
中,因此问题
是一个持久集合
,它有一个null
会话
引用,并将抛出您得到的异常
你这样做的原因是什么
List<Period> periods = _periodDAO.getPeriods(team);
不会被处决。虽然equals()
返回true
(contains()
也返回true
,并由于!
而变为false
),但对象并不相同。列表中的on具有附加的(非空)会话
,因此可以初始化会话。但是你的,defaultPeriod
持有的不能 谢谢大家!!但是TransactionManager仅当时段包含defaultPeriod时才将defaultPeriod中问题的会话字段设置为空,否则-问题将很好地初始化。@OleksandrZ我想看看您的equals()
方法,用于比较时段的实例。虽然Periods
可能包含它,但集合中的一个附加到会话
,而外部的一个则不是。equals方法非常简单,并且基于对时段id的比较。我可以初始化defaultPeriod的问题,只要我不再从db检索此实体,因此,如果我更改代码并添加句点defaultPeriod2=_periodAO.get(defaultPeriod.getId());将不会再次初始化问题,而不是检索期间。谢谢,谢谢!在我的问题中,我没有使用@Transactional作为另一种方法getDefault。很抱歉因此,据我所知,只有在使用query to db时才会创建新事务,而不是初始化现有集合。在@Transactional
中发生的任何事情都将发生在Hibernate会话中,在事务中。当该方法返回时,根据配置,将提交事务
,并关闭会话
。只有当会话
尚未关闭时,才能初始化集合。我认为它不一定必须在同一个事务中。
Period defaultPeriod = team.getDefaultPeriod();
List<Period> periods = _periodDAO.getPeriods(team);
if (!periods.contains(defaultPeriod)) {
defaultPeriod = periods.get(periods.size() - 1);
}