考虑以下实体:
@Entity
public class Employee {
@Id
@GeneratedValue
private Long id;
private String name;
// Assume that Project has a 'name' property
@OneToMany(mappedBy = "manager")
private List<Project> projects;
@OneToOne
private Department department;
// Assume that Computer has a 'model' property
@ManyToOne
private Computer computer;
//...
}
我希望获得给定Project
的所有Employee
个名称。
为了做到这一点,我需要做一个JOIN,所以:
// JPQL query
SELECT p.name FROM Employee e JOIN e.projects p
// Criteria API equivalent (pseudo-code)
Root<Employee> emp = CriteriaQuery#from(Employee.class);
CriteriaQuery#select(emp.get(Employee_.projects).get(Project_.name));
这些查询很好。
但是,我不能这样做:
// JPQL query
SELECT e.projects.name FROM Employee e
// Criteria API equivalent (pseudo-code)
Root<Employee> emp = CriteriaQuery#from(Employee.class);
Join<Employee, Project> empProj = emp.join(Employee_.projects);
CriteriaQuery#select(empProj.get(Project_.name));
由于JPA 2.0规范禁止使用非奇异识别变量。
但是,对于单数属性,我可以使用JOIN访问它们或只是使用标识变量导航到它们,因此以下所有查询都有效并返回同样的结果:
SELECT e.computer.model FROM Employee e
SELECT c.model FROM Employee e JOIN e.computer c
// Criteria API equivalents of the above JPQL (pseudo-code)
Root<Employee> emp = CriteriaQuery#from(Employee.class);
Join<Employee, Computer> empComp = emp.join(Employee_.computer);
CriteriaQuery#select(empComp.get(Computer_.model));
Root<Employee> emp = CriteriaQuery#from(Employee.class);
CriteriaQuery#select(emp.get(Employee_.computer).get(Computer_.model));
我的问题是:
- 什么时候应该使用显式JOIN(在JPQL或Criteria API的join( - )方法中)?
- 两种方法的优点/缺点是什么?
- 被认为比其他人效率更高的人之一吗?
- 如果只是风格问题 - 您更喜欢哪一个?为什么?
答案 0 :(得分:2)
我只考虑属性的类型。 e.computer
是一台计算机,因此我可以在其上调用getModel()
,因此e.computer.model
可以。 e.projects
是一个列表,我无法在列表上调用getName()
,因此e.projects.name
不正常。每次需要访问集合的成员时,您都需要加入。
使用e.computer.id
时,不需要SQL连接(至少不是Hibernate生成的),因为计算机的ID在employee表中,作为外键。因此,使用它比使用显式连接更有效。 e.computer.model
生成SQL连接,这只是风格和偏好的问题。
见2.
我通常更喜欢显式连接,因为......它使它们显式化。如果需要,也可以更容易地将它们转换为左连接。