hibernate中JOIN和JOIN FETCH的区别

请帮我理解在哪里使用常规的JOIN和JOIN FETCH。

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

FROM Employee emp JOIN emp.department dep 

 FROM Employee emp JOIN FETCH emp.department dep 

他们之间有什么区别? 如果是,哪一个要用?

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

但是,区别在于:在第一个查询中,您只返回Hibernate的Employes。 在第二个查询中,您将返回所有相关的Employes 所有部门。

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

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

我build议阅读这个链接,如果你需要应用一些WHERE条件(你可能需要什么): 如何正确地expressionJPQL“join fetch”与“where”子句作为JPA 2 CriteriaQuery?

更新

如果您不使用fetch并且部门继续返回,那是因为您的Employee和Department之间的映射( @OneToMany )是使用FetchType.EAGER设置的。 在这种情况下, FROM Employee任何HQL(带或不带)都会带上所有的Departments。 请记住,默认情况下,所有映射* ToOne( @ManyToOne@OneToOne )都是EAGER。

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

“提取”连接允许使用单个select将关联或值集合与其父对象一起初始化。 这在收集的情况下特别有用。 它有效地覆盖了关联和集合的映射文件的外连接和惰性声明

如果你有(fetch = FetchType.LAZY)属性为集合内的实体(示例波纹pipe),这个“JOIN FETCH”将有效果。

只有“查询发生时”才有效。 而且你也必须知道这一点 :

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

什么时候是关联 – >你的“FETCH”types

如何获取 – >join/select/子select/批处理

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

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

当你使用

 FROM Employee emp JOIN FETCH emp.department dep 

你会得到empemp.dep 。 当你没有使用获取你仍然可以得到emp.dep但hibernate将处理另一个select到数据库来获得该组部门。

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

当您需要使用一个select(一个大查询)获取小数据时,使用预先抓取。 或者使用lazy fetching查询你需要的后者(很多较小的查询)。

使用fetch时:

  • 没有大的不必要的收集/设置你将要获得的实体

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

  • 如果您没有访问权限( 交易方法/类别之外) ,则可能需要该集合;

Dherik:我不确定你说了什么,当你不使用fetch的时候,结果将是types: List<Object[ ]>这意味着Object表的列表而不是Employee列表。

 Object[0] refers an Employee entity Object[1] refers a Departement entity 

当您使用fetch时,只有一个select,结果是包含部门列表的Employee List<Employee>列表。 它覆盖实体的惰性声明。

如果将@oneToOne映射设置为FetchType.LAZY,并使用第二个查询(因为需要将Department对象作为Employee对象的一部分加载),Hibernate将执行的操作是,它将发出查询以获取每个Employee对象的Department对象它从数据库中提取。 在后面的代码中,您可以通过Employee to Department单值关联访问Department对象,而Hibernate不会发出任何查询来获取给定Employee的Department对象。 记得Hibernate仍然发出的查询数量等于它所提取的员工数量。 如果您希望访问所有Employee对象的Department对象,Hibernate将在上述两个查询中发出相同数量的查询