Hibernate中JOIN和JOIN FETCH之间的区别

问题

请帮助我了解在哪里使用常规JOIN和JOIN FETCH。

例如,如果我们有这两个查询

FROM Employee emp
JOIN emp.department dep

FROM Employee emp
JOIN FETCH emp.department dep

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


#1 热门回答(110 赞)

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

但是,区别在于:在第一个查询中,你只返回Hibernate的Employes。在第二个查询中,你将返回关联的Employesall Departments。

因此,如果你使用第二个查询,则无需再次执行新查询来查看数据库以查看每个Employee的Departments。

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

如果你需要应用一些WHERE条件(你可能需要的话),我建议你阅读这个链接:How to properly express JPQL "join fetch" with "where" clause as JPA 2 CriteriaQuery?
更新
如果你不使用fetch并继续返回部门,那是因为你在Employee和Department(a@OneToMany)之间的映射设置为FetchType.EAGER。在这种情况下,任何带有FROM Employee的HQL(withfetchor not)查询都会带来所有部门。请记住,默认情况下,所有映射* ToOne(@ManyToOne@OneToOne)都是EAGER。


#2 热门回答(49 赞)

inthis linki之前提到的评论,请阅读本部分:

"fetch"连接允许使用单个select来初始化值的关联或集合及其父对象。这对于集合来说尤其有用。它有效地覆盖了关联和集合的映射文件的外连接和延迟声明。

如果你在实体内部有一个集合的(fetch = FetchType.LAZY)属性,那么这个"JOIN FETCH"会产生影响(例如波纹管)。

它只会影响"何时应该发生查询"的方法。你还必须知道this

hibernate有两个正交的概念:何时获取关联以及如何获取它。重要的是你不要混淆它们。我们使用fetch来调整性能。我们可以使用lazy来定义在特定类的任何分离实例中始终可用的数据的契约。

何时获取关联 - >你的"FETCH"类型

如何获取 - >加入/选择/子选择/批量

在你的情况下,如果你将部门作为Employee中的集合,FETCH将只有它的效果,在实体中是这样的:

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

当你使用

FROM Employee emp
JOIN FETCH emp.department dep

你会得到empemp.dep。当你没有使用fetch时你仍然可以获得emp.dep但是hibernate会处理另一个选择到数据库以获得那组部门。

所以它只是性能调优的问题,关于你想要在一个查询中获得所有结果(你是否需要它)(或者你需要它),或者你想在需要时查询它(延迟提取)。

当你需要通过一个选择(一个大查询)获取小数据时,使用急切提取。或者使用延迟抓取来查询你需要的内容(许多较小的查询)。

使用fetch时:

  • 你将要获得的实体内没有大量不需要的收集/设置
  • 从应用服务器到数据库服务器的通信太远,需要很长时间
  • 当你无法访问它时(在事务方法/类之外),你可能需要该集合

#3 热门回答(4 赞)

如果你将@oneToOne映射设置为FetchType.LAZY并且你使用第二个查询(因为你需要将Department对象作为Employee对象的一部分加载)Hibernate将要做的是,它将发出查询以获取每个Employee对象的Department对象它从DB获取。稍后在代码中,你可以通过Employee to Department单值关联访问Department对象,Hibernate不会发出任何查询来获取给定Employee的Department对象。记住,Hibernate仍会发出与其获取的Employees数量相等的查询。如果你希望访问所有Employee对象的Department对象,Hibernate将在上述两个查询中发出相同数量的查询