请帮助我了解在何处使用常规 JOIN 以及在何处使用 JOIN FETCH。例如,如果我们有这两个查询
FROM Employee emp
JOIN emp.department dep
和
FROM Employee emp
JOIN FETCH emp.department dep
它们之间有什么区别吗?如果是,什么时候使用哪一个?
原文由 abbas 发布,翻译遵循 CC BY-SA 4.0 许可协议
在我之前在评论中提到的 这个链接 中,阅读这一部分:
“获取”联接允许关联或值集合与其父对象一起使用单个选择进行初始化。这在集合的情况下特别有用。 它有效地覆盖了关联和集合映射文件的外连接和惰性声明。
如果实体内部的集合具有 (fetch = FetchType.LAZY) 属性(示例如下),此“JOIN FETCH”将生效。
而且它只影响“查询何时发生”的方法。你还必须知道 这一点:
hibernate 有两个正交的概念:何时获取关联以及如何获取关联。重要的是不要混淆它们。我们使用 fetch 来调整性能。我们可以使用 lazy 来定义在特定类的任何分离实例中始终可用的数据的契约。
什么时候获取关联 –> 您的“FETCH”类型
它是如何获取的 –> Join/select/Subselect/Batch
在您的情况下,FETCH 只有在您将部门作为 Employee 内部的集合时才会生效,实体中的内容如下所示:
@OneToMany(fetch = FetchType.LAZY)
private Set<Department> department;
当你使用
FROM Employee emp
JOIN FETCH emp.department dep
你会得到 emp
和 emp.dep
。当您不使用 fetch 时,您仍然可以获得 emp.dep
但是 hibernate 将处理另一个对数据库的选择以获取那组部门。
所以这只是性能调整的问题,关于你想在单个查询(急切获取)中获得所有结果(你是否需要它),或者你想在需要它时查询它(延迟获取)。
当您需要通过一次选择(一个大查询)获取小数据时,请使用急切获取。或者使用延迟获取来查询你需要的东西(许多更小的查询)。
在以下情况下使用 fetch:
您将要获得的实体中没有大量 不需要 的集合/集合
从应用服务器到 数据库服务器的通信太远,需要很长时间
当您无法访问它时( 在 事务 方法/类之外),您可能稍后需要该集合
原文由 Angga 发布,翻译遵循 CC BY-SA 4.0 许可协议
15 回答8.4k 阅读
8 回答6.2k 阅读
1 回答4k 阅读✓ 已解决
3 回答2.2k 阅读✓ 已解决
2 回答3.1k 阅读
2 回答3.8k 阅读
3 回答1.7k 阅读✓ 已解决
在这两个查询中,您使用 JOIN 来查询至少关联了一个部门的所有员工。
但是,区别在于:在第一个查询中,您只返回 Hibernate 的 Employes。在第二个查询中,您将返回雇员 和 所有关联的部门。
因此,如果您使用第二个查询,您将不需要执行新的查询来再次访问数据库来查看每个员工的部门。
当您确定需要每个员工的部门时,您可以使用第二个查询。如果不需要部门,请使用第一个查询。
如果您需要应用某些 WHERE 条件(您可能需要),我建议阅读此链接: How to properly express JPQL “join fetch” with “where” clause as JPA 2 CriteriaQuery?
更新
如果您不使用
fetch
并且 Departments 继续返回,是因为您在 Employee 和 Department 之间的映射(a@OneToMany
)设置为FetchType.EAGER
在这种情况下,任何 HQL(带fetch
或不带)查询FROM Employee
将带来所有部门。请记住,所有映射 *ToOne(@ManyToOne
和@OneToOne
)默认情况下都是 EAGER。