多个 children 的 Hibernate N+1 问题

Hibernate N+1 issue for Multiple children

我有一个实体 class,它有多个 children 与 oneToMany 关联:

public class A{
  private Long id;
  private String name;

  @OneToMany(mappedBy = "A", fetch = FetchType.LAZY, cascade = CascadeType.ALL, 
  orphanRemoval = true)
  private List<B>bList= new ArrayList<>();

 @OneToMany(mappedBy = "A", fetch = FetchType.LAZY, cascade = CascadeType.ALL, 
  orphanRemoval = true)
  private List<C>cList= new ArrayList<>();

 @OneToMany(mappedBy = "A", fetch = FetchType.LAZY, cascade = CascadeType.ALL, 
  orphanRemoval = true)
  private List<D>dList= new ArrayList<>();

  //getters and setters

}

对于 B、C 和 D,我设置了 ManyToOne。一句话,他们是bi-directional关系

现在,如果我通过 ID 获取 A,我会看到很多查询被触发,结果是 N+1 问题。为了解决这个问题,我将 @Fetch(FetchMode.SUBSELECT) 添加到上面的所有 oneToMany 关系中,这会导致触发更少的查询。 我的问题是:

  1. 可以使用 @Fetch(FetchMode.SUBSELECT) 还是我可以进一步优化它?

  2. 如果我想通过调用 findAll() 方法获取所有“As”怎么办?多个 children 的语法应该是什么?喜欢

    "select a from A a join fetch a.b then ??"
    列表< A > findAll()

Now, If I fetch A by id, I see a lot of queries get fired which turns out to be N+1 problem. To solve this, I added @Fetch(FetchMode.SUBSELECT) to all of the oneToMany relationships above which cause less queries to be fired.

您并不是说 how/when 这些查询已被触发,因此问题的可能原因是您从 HTTP 端点返回实体,然后将其序列化。使用 @Fetch(FetchMode.SUBSELECT) 是“提高”性能的一种方法,但只有在用于获​​取 A 的基本查询很简单的情况下才能很好地工作。如果它变得太复杂(分页、复杂谓词等),您应该坚持使用默认值 SELECT,而是通过 @BatchSize( size = 32 ) 注释配置适当的批处理大小。批处理大小的一个好的值是您希望返回的 A 个实例的数量,这样每个集合只执行一个查询。如果您允许最大页面大小为例如50,你设置成50就完美了

List< A > findAll()

如果您关心性能和可用性,请不要这样做。允许返回所有元素几乎没有意义,因为任何用户一次都不能处理超过 20 个元素。如前所述,始终对页面大小设置某种上限,以防止可能导致性能问题的误用。