Consider the following Entity:
@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;
//...
}
I want to get all Project names for given Employee.
In order to do this, I need to do a JOIN, so:
// 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));
And these queries are fine.
However, I cannot do:
// 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));
As the JPA 2.0 specification forbids to use non-singular identification variable.
However, for singular attributes, I can access them using either JOIN or simply navigating to them using identification variable, so all of the following queries are valid and return the same result:
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));
My questions are:
– when should I use explicit JOIN (either in JPQL or Criteria API’s join(-) method)?
– what are the advantages / disadvantages of both approaches?
– is one of those considered more efficient than the other?
– if it’s just a matter of style – which one would you prefer and why?
I just think about the type of the attribute.
e.computeris a Computer, and I can thus callgetModel()on it, soe.computer.modelis OK.e.projectsis a List, and I can’t callgetName()on a List, soe.projects.nameis not OK. You need a join each time you need to access a member of a collection.When using
e.computer.id, a SQL join is not necessary (and not generated, at least by Hibernate), because the ID of the computer is in the employee table, as a foreign key. Using it is thus more efficient than using an explicit join.e.computer.modelgenerates a SQL join, and it’s just a matter of style and preference.See 2.
I usually prefer explicit joins, because… it makes them explicit. It’s also easier to transform them into left joins if needed.