【问题标题】:why LazyInitializationException was not thrown?为什么没有抛出 LazyInitializationException?
【发布时间】:2020-03-27 19:34:25
【问题描述】:

我创建了与OrgHV 一对一映射的实体Org

@Table(name="ORG_CHART")
@Entity
public class Org {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="ORG_ID")
    private int id;

    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JoinColumn(name = "ORG_ID")
    private OrgHV orgHV;
    //getters and Setters
}

在服务中,我使用 Spring data Jpa repo 检索了 Org 的所有实体,并且由于延迟加载 OrgHV 直到我调用 org.getOrgHV() 才会被获取。问题是我在打电话给repo.findAll() 之后才这样做,所以会话/事务已关闭(如果我错了,请纠正我)?为什么代码运行良好,为什么没有抛出LazyInitializationException

public orgService()
{
   List<Org> orgs = orgRepo.findAll();
   for (Org org: orgs) 
   {  
      orgRepo.findAll();  
      OrgHV orgHv = org.getOrgHV();
      System.out.pringLn(orgHv.getId());
   }
}

【问题讨论】:

  • 这能回答你的问题吗? Making a OneToOne-relation lazy
  • 我也很好奇为什么这个例子中没有抛出 LazyInitializationException。 FetchType 是 LAZY,事务已经完成,为什么它还在工作?

标签: java hibernate spring-boot jpa spring-data


【解决方案1】:

不会抛出异常,因为spring.jpa.open-in-view 属性,默认设置为true (source),它注册OpenEntityManagerInViewInterceptor。这会将 JPA EntityManager 绑定到线程以完成请求的整个处理,因此即使 findAll() 方法和事务一样完成,仍然可以获取延迟加载的字段。

doc中所述

Spring Web 请求拦截器将 JPA EntityManager 绑定到线程,以完成请求的整个处理。适用于“在视图中打开 EntityManager”模式,即允许在 Web 视图中延迟加载,尽管原始事务已经完成

当 Spring-Boot 应用程序启动时,您甚至会收到警告(如果该属性未明确设置):

WARN 8363 --- [           main] JpaBaseConfiguration$JpaWebConfiguration : spring.jpa.open-in-view is enabled by default. Therefore, database queries may be performed during view rendering. Explicitly configure spring.jpa.open-in-view to disable this warning

如果要查看预期的异常,请在 application.properties 中设置

spring.jpa.open-in-view=false

【讨论】:

    猜你喜欢
    • 2011-12-12
    • 2018-01-05
    • 2018-02-04
    • 2021-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-26
    • 1970-01-01
    相关资源
    最近更新 更多