Spring JPA优化传递@ManyToOne获取

时间:2017-12-13 15:55:33

标签: java mysql spring hibernate jpa

在我的项目中,我有三个这样的实体:

@Entity
public class A {
    @Id
    private int id;
}

@Entity
public class B {
    @Id
    private int id;
    @ManyToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}, optional = false)
    @OnDelete(action = OnDeleteAction.CASCADE)
    private A a;
}

@Entity
public class C {
    @Id
    private int id;
    @ManyToOne(cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}, optional = false)
    @OnDelete(action = OnDeleteAction.CASCADE)
    private B b;
}

正如您所看到的,CA具有明显的ManyToOne-Relationship关系。 现在,我想使用C获取具有特定A的所有JpaRepository

public interface CRepository extends JpaRepository<C, Integer> {
    List<C> findAllByBA(A a);
}

这导致了以下Hibernate sql查询(很好):

  

休眠:选择...来自c c0_交叉连接b b1_其中c0_.b_id = b1_.id和b1_.a_id =?

但之后我得到了另一个查询,每个不同的B(可能是几千,所以不是很好):

  

休眠:选择...从b b0_ inner加入一个a1_ on b0_.a_id = a1_.id其中b0_.id =?

显然,这可以通过使用所有三个表的单个连接来解决。但如何告诉Hibernate 这样做而不会失去JpaRepository抽象的便利性?

1 个答案:

答案 0 :(得分:1)

额外的,不需要的查询是由关联渴望的事实引起的。为了避免加载B,你应该使关联变得懒惰:

@ManyToOne(fetch: FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH}, optional = false)

我通常会让每个协会都懒惰。如果你对Bs不感兴趣,或者事先不知道是否需要加载Bs,那么使关联变得懒惰可以避免加载它们。如果您知道您希望将B与C一起加载,那么您只需在查询中明确加载它们:

@Query("select c from C c left join fetch c.b where c.b.a = ?")