请帮我弄明白在什么情况下使用普通 JOIN,在什么情况下使用 JOIN FETCH。
例如,如果我们有以下两个查询
FROM Employee emp
JOIN emp.department dep
和
FROM Employee emp
JOIN FETCH emp.department dep
它们有什么区别吗?如果有,什么时候使用哪个?
在这两个查询中,您使用 JOIN 来查询至少与一个部门相关联的所有员工。
但不同之处在于:在第一个查询中,只返回 Hibernate 的雇员。而在第二个查询中,返回的是雇员和所有相关部门。
因此,如果使用第二个查询,就不需要再做一个新的查询,再次访问数据库来查看每个雇员的部门。
如果确定需要每个雇员的部门信息,可以使用第二个查询。如果不需要部门信息,则使用第一个查询。
如果您需要应用一些 WHERE 条件(您可能会需要),我建议您阅读以下链接: https://stackoverflow.com/questions/5816417/how-to-properly-express-jpql-join-fetch-with-where-clause-as-jpa-2-criteriaq
更新
如果您没有使用 fetch
,而部门仍然被返回,那是因为您在雇员和部门(一个 @OneToMany
)之间的映射设置了 FetchType.EAGER
。在这种情况下,任何使用 FROM Employee
的 HQL(无论是否使用 fetch
)查询都会带来所有部门。请记住,所有 *ToOne 映射(@ManyToOne
和 @OneToOne
)默认都是 EAGER。
在 此链接 中,我之前在评论中提到过,请阅读这一部分 :
"fetch"连接允许使用单个选择来初始化关联或值集合。 使用单个选择将关联或集合及其父对象初始化。 这对集合尤其有用。它 有效地覆盖了外部连接和映射文件中的懒惰声明。 映射文件**中的外部连接和懒惰声明。
如果实体内部的集合具有 (fetch = FetchType.LAZY) 属性,这个 "JOIN FETCH" 就会产生作用(示例如下)。
它只对 "when the query should happen" 方法有效。您还必须知道 this:
hibernate 有两个正交的概念:何时获取关联和如何获取关联。 获取。重要的是,你不能混淆它们。我们使用 fetch 来调整性能。我们可以使用 lazy 来定义 在特定类的任何分离实例中,哪些数据总是可用的。 类的任何分离实例中始终可用的数据。
何时获取关联 --> 你的 "FETCH" 类型
如何获取 --> 连接/选择/子选择/批处理
在您的案例中,FETCH 只有在您将部门作为 Employee 中的一个集合(在实体中类似于这样)时才会有效果:
@OneToMany(fetch = FetchType.LAZY)
private Set<Department> department;
当您使用
FROM Employee emp
JOIN FETCH emp.department dep
当您不使用 fetch 时,您仍然可以获得 emp.dep
,但 hibernate 会处理另一个数据库选择,以获得该部门集。
因此,这只是一个性能调整的问题,你是想在一次查询中得到所有结果(无论是否需要)(急于获取),还是想在需要时再查询(懒于获取)。
当需要通过一次选择(一次大查询)获取少量数据时,使用急切获取。或者使用 "懒取回 "来查询后面需要的数据(多个小查询)。
在以下情况下使用 fetch
要获取的实体内部没有大的不需要的集合/集
从应用服务器到数据库服务器的通信距离太远,需要很长时间
当您无法访问该集合(在事务方法/类之外)时,您可能需要该集合。
Dherik : 我不太确定你说的话,当你不使用 fetch 时,结果的类型将是:"List<Object[]>",这意味着对象表列表,而不是雇员列表。
Object[0] refers an Employee entity
Object[1] refers a Departement entity
使用 fetch 时,只需选择一次,结果就是包含部门列表的雇员列表 "List