【问题标题】:Why Hibernate sometimes ignores FetchMode.JOIN?为什么 Hibernate 有时会忽略 FetchMode.JOIN?
【发布时间】:2016-08-16 06:14:38
【问题描述】:

我有一个具有@ManyToOne 关系的实体,我想通过单个查询来检索它,因此使用@Fetch(FetchMode.JOIN)。有时 Hibernate 不尊重这一点并发出 N+1 SELECTs。 有时我的意思是,因为我不知道是什么触发了它,所以我有一些案例在同一个类中针对不同的查询可能会发生或不会发生。

这是一个简化的实体,带有我使用的注释:

@Entity
public class Employee {

    @ManyToOne
    @Fetch(FetchMode.JOIN)
    private Department department;

}

CriteriaQuery<Employee> criteriaQuery = criteriaBuilder.createQuery(Employee.class);

Root<Employee> root = criteriqQuery.from(Employee.class);

TypedQuery<Employee> typedQuery = entityManager.createQuery(criteriaQuery);

List<Employee> employees = typedQuery.getResultList();

我希望单个查询同时获取 Employee 及其 Department,类似于

select ... from Employee join Department on ...

相反,我首先选择所有 N Employees,然后选择 N SELECTs 用于所有 Departments(考虑没有缓存)。

我发现了许多类似的问题,但他们的回答提出了解决方法,并没有解释为什么会发生这种情况。请避免建议使用延迟加载的答案:这不是我要的。

【问题讨论】:

    标签: java hibernate jpa optimization


    【解决方案1】:

    规则很简单:查询忽略获取模式。当你写一个查询时,你是在告诉什么是连接的,什么是没有连接的。

    仅当使用 EntityManager.find(class, id) 等方法加载实体或浏览其他实体图并加载其关联时,才会考虑获取模式。

    【讨论】:

    • 谢谢!就是这样:Criteria API 忽略 @Fetch,但使用 Root.fetch()(即 JPA)我可以获得相同的结果。
    • @GiovanniLovato 感谢您的提示,Root.fetch 达到了相同的结果 - 这非常有帮助。我只需要补充一点,生成的Fetch 可以转换为Join 以供进一步使用。另请参阅此链接:stackoverflow.com/a/17307248/7095884
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-17
    • 1970-01-01
    • 2018-05-27
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多