我正在阅读一些带有 Hibernate 的实体:
Criteria criteria = session.createCriteria(…);
List<Entity> list = (List<Entity>) criteria.list();
现在我正在迭代此列表,并希望将 Runnable
内的每个对象发送到 Executor
。因此,我使用 RunnableBean
。
for (Entity entity : list) {
IRunnableBean runnableBean = (IRunnableBean)
applicationContext.getBean("myRunnableBean", IRunnableBean.class);
runnableBean.setEntity(entity);
executor.execute(runnableBean);
}
RunnableBean
看起来像这样:
RunnableBean implements IRunnableBean {
// Setter
@Transactional
void run() {
entity.getMyCollection();
}
}
当我访问该集合时,我收到org.hibernate.LazyInitializationException
(没有 session 或 session 已关闭
)。
在 Spring 的日志中,我看到事务方法 run()
已正确添加。我做错了什么?
最佳答案
我猜你正在使用Spring's OpenSessionInViewFilter 。如果是这样,则这种行为是预期的。过滤器将数据库连接放入线程本地上下文中,这在您的 RunnableBean 中不可用。
由于 myCollection
没有立即加载,Spring 无权访问 RunnableBean
内的数据库连接,因此无法加载它。您需要:
- 在
RunnableBean
中创建一个封闭的 session 包装器; - 将集合的 ID 传递给
RunnableBean
,而不是传递对象,并将集合加载到RunnableBean
或者,您可以让实体急切地加载 myCollection
,但这会使整体加载过程变慢。
关于java - 访问 Runnable 中的集合时出现 LazyInitializationException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13290404/