JPA2:N + 1即使使用JOIN查询也会选择

时间:2013-07-10 12:33:50

标签: java jpa join eager

在我的应用程序中,我有一个实体A,其中包含应该急切获取的实体B列表:

@Entity
public class A
{
    ...
    /* @OrderBy("cValue.id ASC") */
    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name="A_ID", nullable=false)
    private List<B> BEntries = new ArrayList<B>();
    ...
}

@Entity
public class B
{
    ...
    @ManyToOne
    @JoinColumn(name = "C_ID", nullable = false)
    private C cValue;
    ...
}

为了获得A的列表,我首先做了这个简单的查询:

CriteriaBuilder critBuilder = em.getCriteriaBuilder();
CriteriaQuery<A> critQuery = critBuilder.createQuery(A.class);
Root<A> critRoot = critQuery.from(A.class);
critQuery.select(critRoot);

但是我看到Hibernate在数据库上做了N + 1个选择查询,在A类上做了1次,在B类上做了N(其中N是数据库中A的元组数)。

我非常惊讶的是,对于急切的提取,Hibernate并没有直接进行LEFT JOIN查询。

所以我首先尝试使用Hibernate的注释@Fetch(FetchMode.JOIN),但它没有按预期工作。

所以我使用以下附加说明转换了我的列表查询:

Join<A,B> joinAB = critRoot.join(A_.BEntries, JoinType.LEFT);
joinAB.join(B_.cValue, JoinType.LEFT);

好的,现在生成的SQL查询包含了所有需要的LEFT JOIN来热切地构建完整的A对象......但是它仍然在B表上执行其他N个查询! 我首先想到的是它来自我在Bentries参数上的@OrderBy注释,但即使被删除,它仍然在进行N + 1选择而不是1 ...

知道为什么它会像这样吗?...甚至为什么默认情况下它不会在实体中急切获取的集合中进行LEFT JOIN?

0 个答案:

没有答案