【问题标题】:Hibernate getOne() not working with background threadHibernate getOne() 不使用后台线程
【发布时间】:2021-01-27 15:33:11
【问题描述】:

我遇到了一个场景,我正在返回 API 响应(请求线程)并将任务委托给后台线程。 在后台线程中,我调用hibernate的T getOne(ID id);来获取一些信息,导致

org.hibernate.LazyInitializationException: 无法初始化代理 - 线程类中没有会话

但是,当使用 JPA 查询 @Query("some query")本机查询 @Query(value = "some query", native = true)JdbcTemplate 执行数据库操作时,它在后台线程。

有人可以帮我理解为什么会出现这种行为吗?

仅供参考。我正在使用 Spring Boot 1.4.2Hibernate 5.0.11

【问题讨论】:

  • 尚未检查,但使用其他默认方法可能会观察到相同的行为,例如 List findAll();
  • LazyInitializationException 意味着您(休眠)正在尝试在活动会话关闭时从数据库中获取内容。修复您的查询以获得会话期间所需的一切。此外,hibernate 绑定到特定线程,因此它可能绑定到初始线程而不是后台线程。
  • 好的。每当请求对象时,应再次建立/打开会话?为什么 JPAQL/HQL 不会发生同样的情况?
  • 不完全知道——你说的是本机查询,所以我怀疑那时它只是进入 JDBC。基本上,您将需要研究 Hibernate 和后台线程,我认为您不会找到任何简单的答案。我记得曾经在这方面工作过一段时间,但我认为我没有找到一个好的解决方案。一旦休眠开始锁定线程,就很难弄清楚发生了什么。

标签: java multithreading spring-boot hibernate jpa


【解决方案1】:

T getOne(ID id) 依赖于执行实体延迟加载的EntityManager.getReference()。所以为了保证实体的有效加载,需要对其调用方法。

基本上,您的线程无法找到任何活动会话 context.Hibernate 在需要初始化延迟获取的与另一个没有活动会话上下文的实体的关联时会抛出 LazyInitializationException。 您 FetchType.EAGER 在您与您尝试获取的对象的任何关联中。但是,每次您尝试获取对象时,它都会有自己的影响,例如不需要的查询执行。

最佳解决方案将使用Optional<T> findById(ID id) 您可以使用obj.isPresent() 检查实体是否存在并继续。

【讨论】:

    猜你喜欢
    • 2011-01-21
    • 2011-09-16
    • 2015-08-23
    • 1970-01-01
    • 2023-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-29
    相关资源
    最近更新 更多