使用 JPA 和 Hibernate 时,JOIN 和 JOIN FETCH 有什么区别

2022-08-31 05:29:33

请帮助我了解在何处使用常规 JOIN 以及 JOIN FETCH 的位置。例如,如果我们有这两个查询

FROM Employee emp
JOIN emp.department dep

FROM Employee emp
JOIN FETCH emp.department dep

它们之间有什么区别吗?如果是,什么时候使用哪一个?


答案 1

在这两个查询中,您将使用 JOIN 查询至少关联了一个部门的所有员工。

但是,不同之处在于:在第一个查询中,您只返回休眠的 Employes。在第二个查询中,您将返回“雇员”所有关联的部门。

因此,如果使用第二个查询,则无需执行新查询即可再次点击数据库以查看每个员工的部门。

当您确定需要每个员工的部门时,可以使用第二个查询。如果不需要部门,请使用第一个查询。

如果您需要应用一些 WHERE 条件(您可能需要什么),我建议您阅读此链接:如何将 JPQL “join fetch” 与 “where” 子句正确表示为 JPA 2 CriteriaQuery?

更新

如果不使用并且继续返回部门,则是因为员工和部门 (a) 之间的映射设置为 。在这种情况下,任何 HQL(带或不带)查询都将带来所有部门。请记住,默认情况下,所有映射 *ToOne ( 和 ) 都是 EAGER 的。fetch@OneToManyFetchType.EAGERfetchFROM Employee@ManyToOne@OneToOne


答案 2

在我之前提到的这个链接上的评论,阅读这部分:

“fetch”联接允许使用单个选择来初始化值的关联或集合及其父对象。这在集合的情况下特别有用。它有效地覆盖了关联和集合的映射文件的外部联接和惰性声明

这个“JOIN FETCH”将具有(fetch = FetchType.LAZY)属性用于实体内部的集合(示例波纹管)将具有效果。

它只影响“何时应该发生查询”的方法。您还必须知道这一点

冬眠有两个正交的概念:什么时候获取关联以及如何获取。重要的是不要混淆它们。我们使用抓取来调整性能。我们可以使用 lazy 来定义一个协定,说明哪些数据在特定类的任何分离实例中始终可用。

何时获取关联 -->“FETCH”类型

它是如何获取的 --> 加入/选择/部分选择/批处理

在你的例子中,FETCH只有在员工内部将部门作为集合时才有效,在实体中如下所示:

@OneToMany(fetch = FetchType.LAZY)
private Set<Department> department;

当您使用时

FROM Employee emp
JOIN FETCH emp.department dep

你会得到和.当你没有使用fetch时,你仍然可以得到,但休眠将处理另一个选择到数据库,以获得那组部门。empemp.depemp.dep

所以它只是一个性能调优的问题,关于你想在单个查询中获取所有结果(你是否需要它)(eager fetching),或者你想在你需要的时候查询它(懒惰获取)。

当您需要通过一个选择(一个大查询)获取小数据时,请使用 eager fetch。或者使用惰性抓取来查询后期(许多较小的查询)需要什么。

在以下情况下使用抓取:

  • 您即将获得的实体内没有大型不需要的集合/集合

  • 从应用程序服务器到数据库服务器的通信太远,需要很长时间

  • 当您无法访问该集合时,您可能需要该集合(在事务方法/类之外


推荐