我正在阅读一些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
(no session or session was closed
)。在Spring的日志中,我看到正确添加了事务方法
run()
。我究竟做错了什么? 最佳答案
我猜您正在使用Spring's OpenSessionInViewFilter。如果是这样,这种行为是预期的。筛选器将数据库连接放在线程本地上下文中,而在RunnableBean
中不可用。
由于myCollection
并不急于加载,因此Spring无法访问RunnableBean
内部的数据库连接,因此无法加载它。你需要:
在您的RunnableBean
中创建一个封闭的会话包装器;
将集合的ID传递给RunnableBean
而不是传递对象,并将集合加载到RunnableBean
另外,您可以使您的实体急于加载myCollection
,但这会使整体加载过程变慢。