JPA-join-Tutorial
JPA-join-Tutorial
Entities Example
The following JPQL selects from two entities.
Example
The following code is from Professor.java.
package com.java.common;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
@Entity
public class Professor {
@Id
private int id;
private String name;
private long salary;
@Temporal(TemporalType.DATE)
private Date startDate;
@OneToOne
private Address address;
@OneToMany(mappedBy="employee")
private Collection<Phone> phones = new ArrayList<Phone>();
@ManyToOne
private Department department;
@ManyToOne
private Professor manager;
@OneToMany(mappedBy="manager")
private Collection<Professor> directs = new ArrayList<Professor>();
@ManyToMany(mappedBy="employees")
private Collection<Project> projects = new ArrayList<Project>();
}
The following code is from Address.java.
package com.java.common;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Address {
@Id
private int id;
private String street;
private String city;
private String state;
private String zip;
package com.java.common;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.transaction.annotation.Transactional;
@Transactional
public class PersonDaoImpl {
public void test(){
prepareData();
List l = em.createQuery("SELECT d, m FROM Department d, Professor m WHERE d = m.
department").getResultList();
for(Object p:l){
System.out.println(p);
}
}
p.setDepartment(d);
d.getProfessors().add(p);
em.persist(p);
em.persist(d);
}
@PersistenceContext
private EntityManager em;
}
package com.java.common;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
@Entity
public class Phone {
@Id
private long id;
private String number;
private String type;
@ManyToOne
Professor employee;
package com.java.common;
import java.util.ArrayList;
import java.util.Collection;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.ManyToMany;
@Entity
@Inheritance
public class Project {
@Id
protected int id;
protected String name;
@ManyToMany
protected Collection<Professor> employees = new ArrayList<Professor>();
package com.java.common;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
@Entity
public class Department {
@Id
private int id;
private String name;
@OneToMany(mappedBy="department")
private Set<Professor> employees = new HashSet<Professor>();
public int getId() {
return id;
}
List l = em.createQuery(
"SELECT e FROM Professor e JOIN FETCH e.address")
.getResultList();
Example
The following code is from Department.java.
package com.java.common;
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToMany;
@Entity
public class Department {
@Id
private int id;
private String name;
@OneToMany(mappedBy="department")
private Set<Professor> employees = new HashSet<Professor>();
package com.java.common;
import java.util.ArrayList;
import java.util.Collection;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.ManyToMany;
@Entity
@Inheritance
public class Project {
@Id
protected int id;
protected String name;
@ManyToMany
protected Collection<Professor> employees = new ArrayList<Professor>();
package com.java.common;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
@Entity
public class Phone {
@Id
private long id;
private String number;
private String type;
@ManyToOne
Professor employee;
package com.java.common;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
@Entity
public class Professor {
@Id
private int id;
private String name;
private long salary;
@Temporal(TemporalType.DATE)
private Date startDate;
@OneToOne
private Address address;
@OneToMany(mappedBy="employee")
private Collection<Phone> phones = new ArrayList<Phone>();
@ManyToOne
private Department department;
@ManyToOne
private Professor manager;
@OneToMany(mappedBy="manager")
private Collection<Professor> directs = new ArrayList<Professor>();
@ManyToMany(mappedBy="employees")
private Collection<Project> projects = new ArrayList<Project>();
package com.java.common;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Address {
@Id
private int id;
private String street;
private String city;
private String state;
private String zip;
package com.java.common;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.transaction.annotation.Transactional;
@Transactional
public class PersonDaoImpl {
public void test() {
prepareData();
List l = em.createQuery(
"SELECT e FROM Professor e JOIN FETCH e.address")
.getResultList();
for (Object p : l) {
printResult(p);
}
}
p.setDepartment(d);
d.getProfessors().add(p);
em.persist(p);
em.persist(phone);
em.persist(address);
em.persist(d);
}
@PersistenceContext
private EntityManager em;
}
LEFT JOIN
The LEFT JOIN statement is similar to the JOIN statement. The main difference is
that a LEFT JOIN statement includes all rows of the entity or table referenced on the
left side of the statement.
I use that in the following example to select all Authors with the lastName “Janssen”
and their Books. If the database contains a Book for a specific Author, the query
returns it as the second element in the Object[]. Otherwise, that array element is null.
A simple JOIN statement would only return the Authors who have written a Book.
The second element of the Object[] would never be null.
1 List<Object[]> authors = em.createQuery("SELECT a, b FROM Author a LEFT JOIN a.books
Hibernate generates the following SQL statement for this query. It selects all columns
mapped by the Author and Book entities and uses the defined association to create a
left join between the Book and the Author tables.
1
2
3 16:54:10,510 DEBUG [org.hibernate.SQL] -
select
4 author0_.id as id1_0_0_,
5 book2_.id as id1_1_1_,
6 author0_.firstName as firstNam2_0_0_,
7 author0_.lastName as lastName3_0_0_,
author0_.version as version4_0_0_,
8
book2_.publisherid as publishe5_1_1_,
9 book2_.publishingDate as publishi2_1_1_,
10 book2_.title as title3_1_1_,
11 book2_.version as version4_1_1_
12 from
Author author0_
13 left outer join
14 BookAuthor books1_
15 on author0_.id=books1_.authorId
16 left outer join
17 Book book2_
on books1_.bookId=book2_.id
18 where
19 author0_.lastName='Janssen'
20
21
JOIN FETCH
The FETCH keyword of the JOIN FETCH statement is JPA-specific. It tells the
persistence provider to not only join the 2 database tables within the query but to
also initialize the association on the returned entity. You can use it with a JOIN and
a LEFT JOIN statement.
Let’s change the first example and replace the JOIN statement with a JOIN
FETCH statement.
List<Author> authors = em.createQuery("SELECT a FROM Author a
1JOIN FETCH a.books b WHERE b.title LIKE '%Hibernate%'", Author.class).getResultList();
The JPQL query selects Author entities. But as you can see in the SQL statement,
Hibernate now selects all columns mapped by the Author and the Book entity.
Hibernate then maps the result set to Author and Book entities. It uses
the Book entities to initialize the books attribute of each Author entity before it returns
a List of Author entities.
1
2
3 16:57:53,384 DEBUG [org.hibernate.SQL] -
4 select
author0_.id as id1_0_0_,
5 book2_.id as id1_1_1_,
6 author0_.firstName as firstNam2_0_0_,
7 author0_.lastName as lastName3_0_0_,
8 author0_.version as version4_0_0_,
book2_.publisherid as publishe5_1_1_,
9
book2_.publishingDate as publishi2_1_1_,
10 book2_.title as title3_1_1_,
11 book2_.version as version4_1_1_,
12 books1_.authorId as authorId2_2_0__,
13 books1_.bookId as bookId1_2_0__
from
14 Author author0_
15 inner join
16 BookAuthor books1_
17 on author0_.id=books1_.authorId
18 inner join
Book book2_
19 on books1_.bookId=book2_.id
20 where
21 book2_.title like '%Hibernate%'
22
23