java - 访问 Runnable 中的集合时出现 LazyInitializationException

标签 java multithreading spring hibernate spring-transactions

我正在阅读一些带有 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/

相关文章:

java - 用用户输入填充二维数组(整数到二进制)

java - 在 Windows 7 上在 32 位和 64 位 JDK 平台之间切换

java - 骡子 ESB : How the threads names are managed?

java - Spring 启动 hibernate : cannot delete child object separately

android - 将 Spring for android 依赖项添加到 gradle + Android studio 项目

java - Java 8 中查询结果数据库的最优化方式

java - Java中按大写字母分割

java - 比构造函数快?

WinForm 应用程序的 C# 多线程框架

c# - 线程监控 Queue<Actions>