我正在阅读一些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.LazyInitializationExceptionno session or session was closed)。

在Spring的日志中,我看到正确添加了事务方法run()。我究竟做错了什么?

最佳答案

我猜您正在使用Spring's OpenSessionInViewFilter。如果是这样,这种行为是预期的。筛选器将数据库连接放在线程本地上下文中,而在RunnableBean中不可用。

由于myCollection并不急于加载,因此Spring无法访问RunnableBean内部的数据库连接,因此无法加载它。你需要:


在您的RunnableBean中创建一个封闭的会话包装器;
将集合的ID传递给RunnableBean而不是传递对象,并将集合加载到RunnableBean


另外,您可以使您的实体急于加载myCollection,但这会使整体加载过程变慢。

07-27 17:18