【问题标题】:Lazy fetching with @OneToOne使用 @OneToOne 进行延迟获取
【发布时间】:2020-10-27 16:22:10
【问题描述】:

我有两个 @OneToOne 实体:

...
public class A {
  
   ...
   
   @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
   @JoinColumn(name = "b_id", nullable = false)
   private B b; 

   ...
}

...
public class B {

...

@OneToOne(fetch = FetchType.LAZY, mappedBy = "b", cascade = CascadeType.ALL, orphanRemoval = true)
private A a;

...
}

我正在使用 spring data JPA JpaRepository 来获取所有实体(findAll() 方法)。

是否可以使用延迟初始化的 A 属性获取所有 B 实体(当我获取所有 时不获取 A 属性B 个实体?如果没有,这种情况下是否可以避免 N+1 选择?

编辑:我的问题与我如何使 JPA OneToOne 关系变得懒惰How can I make a JPA OneToOne relation lazy 不同,因为我的问题是相反的,我想获取父实体和/或在获取它时避免 N+1 选择。

【问题讨论】:

标签: hibernate jpa spring-data-jpa


【解决方案1】:

编辑:我的问题与 How can I make a JPA OneToOne 不同 关系懒惰 我怎样才能使 JPA OneToOne 关系变得懒惰,因为我的 是其他方式,我想获取父实体和/或避免 获取时选择 N+1。

唯一的方法是将@OneToOne 关联更改为单向

但您使用的是双向 @OneToOne 关联,因此不可能***。父关联将始终执行FetchType.EAGER。原因是

对于每个托管实体,“持久性上下文”都需要 实体类型和标识符,因此必须知道子标识符 加载父实体时,唯一的方法是找到 关联的“A 类”主键是执行第二次选择。

***:如果您想避免第二次选择,Bytecode enhancement 是唯一可行的解​​决方法。但是,它仅在父端使用@LazyToOne(LazyToOneOption.NO_PROXY) 注释并且子端使用@MapsId 时才有效。

奖励:
映射@OneToOne 的最有效方法由伟大的 Vlad here 描述。简而言之,使用@MapsId

【讨论】:

    【解决方案2】:

    是否可以通过延迟初始化的 A 获取所有 B 实体 属性(当我获取所有 B 实体时不获取 A 属性?如果 不是,这种情况下是否可以避免N+1 select?

    当您使用属性访问而不是字段访问时,也许有可能。通过字段访问,一对一关联必须急切地初始化,因为它不能使用代理。不能,因为如果对象不存在,该字段必须为空。通过属性访问,这可以推迟到第一次调用 getter,但这也可能是一个问题。

    也许您可以使用 fetch join 来避免 N + 1 问题或使用 DTO?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-05
      • 1970-01-01
      • 1970-01-01
      • 2011-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-03
      相关资源
      最近更新 更多