首页 > 解决方案 > 急切地加载一个标记为懒惰的集合?

问题描述

我有以下课程:

public class Service {

  @Column(name = "LABEL")
  @NotNull
  private String label;


  @OneToMany(fetch = FetchType.LAZY)
  @JoinColumn(name = "SERVICE_ID")
  private Set<User> users;


  @OneToMany(fetch = FetchType.LAZY)
  @JoinColumn(name = "SERVICE_ID")
  private Set<Account> accounts;

}
public class Account {

  /** Other properties **/

  @ManyToMany(fetch = FetchType.LAZY)
  @JoinTable(name = "USER_ACCOUNT_RELATION", joinColumns =
    {@JoinColumn(name = "ACCOUNT_ID")}, inverseJoinColumns =
    {@JoinColumn(name = "USER_ID")})
  private Set<User> users;

}

我有ServiceRepository以下查询:


    // QUERY1 : users and accounts won't be needed for further processing
    @Query("select service from LcmEtcService service" +
    " inner join service.department dept " +
    " where dept.id = :departmentId" )
  Set<Service> getServicesByDepartment(@Param("departmentId") Long departmentId);

    // QUERY2 : users and accounts will be needed for further processing
    @Query("select service from Service service" +
    " inner join service.department dept " +
    " left join fetch service.users " +
    " left join fetch service.accounts accounts " +
    " left join fetch accounts.users " +
    " where dept.id = :departmentId " )
  Set<Service> getFullServicesByDepartment(@Param("departmentId") String departmentId);

我正在尝试优化QUERY2的时间,因为它需要很长时间才能获得请求超时。

注意:我不想增加超时

我尝试了很多东西,但我仍然无法让它工作,我不明白为什么它不起作用。

使用批量大小

我尝试如下注释我的所有收藏,但这不起作用。

  @OneToMany(fetch = FetchType.LAZY)
  @Fetch(FetchMode.SUBSELECT)
  @BatchSize(size = 32)

将 Service.users 从 LAZY 更改为 EAGER

这实际上可行,但现在Query1需要更多时间才能完成(但不会超时)。=> 我不能使用这个解决方案。

使用动态实体图

我尝试如下注释我的 Query2,但它仍然不起作用。


    // QUERY2 : users and accounts needed here
    @Query("select service from Service service" +
    " inner join service.department dept " +
    " left join fetch service.users " +
    " left join fetch service.accounts accounts " +
    " left join fetch accounts.users " +
    " where dept.id = :departmentId " )
  @EntityGraph(attributePaths = {"users"})
  Set<Service> getFullServicesByDepartment(@Param("departmentId") String departmentId);

所以我的问题是:

  1. Service.user从更改LazyEager给出了更好的时间响应。我认为 usingleft join fetch service.users足以强制加载。例如相当于:
public class Service {

  @OneToMany(fetch = FetchType.EAGER)
  @JoinColumn(name = "SERVICE_ID")
  private Set<User> users;

}

=> 这是真的吗?如果是这样,为什么在使用时请求超时left join fetch service.users但在集合设置为时没有eager

  1. 如何选择大小的值@BatchSize(size = 32)?我需要尝试其他值吗?(我也尝试了 15 和 60 但仍然得到相同的结果)。

  2. 通过注释Query2 @EntityGraph(attributePaths = {"users"}),我还需要写left join fetch service.users吗?

  3. 还有什么我可以尝试的吗?

注意:所有需要的索引都已在数据库中设置

标签: javahibernatejpaquery-optimization

解决方案


推荐阅读