BAEL-2811: Added sample code for jpa joins (#6691)
This commit is contained in:
parent
afd8fe5c98
commit
59f3b02e87
|
@ -0,0 +1,45 @@
|
|||
package com.baeldung.joins.model;
|
||||
|
||||
import java.util.List;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
|
||||
@Entity
|
||||
public class Department {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private long id;
|
||||
|
||||
private String name;
|
||||
|
||||
@OneToMany(mappedBy = "department")
|
||||
private List<Employee> employees;
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<Employee> getEmployees() {
|
||||
return employees;
|
||||
}
|
||||
|
||||
public void setEmployees(List<Employee> employees) {
|
||||
this.employees = employees;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package com.baeldung.joins.model;
|
||||
|
||||
import java.util.List;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "joins_employee")
|
||||
public class Employee {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private long id;
|
||||
|
||||
private String name;
|
||||
|
||||
private int age;
|
||||
|
||||
@ManyToOne
|
||||
private Department department;
|
||||
|
||||
@OneToMany(mappedBy = "employee")
|
||||
private List<Phone> phones;
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public int getAge() {
|
||||
return age;
|
||||
}
|
||||
|
||||
public void setAge(int age) {
|
||||
this.age = age;
|
||||
}
|
||||
|
||||
public Department getDepartment() {
|
||||
return department;
|
||||
}
|
||||
|
||||
public void setDepartment(Department department) {
|
||||
this.department = department;
|
||||
}
|
||||
|
||||
public List<Phone> getPhones() {
|
||||
return phones;
|
||||
}
|
||||
|
||||
public void setPhones(List<Phone> phones) {
|
||||
this.phones = phones;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package com.baeldung.joins.model;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
@Entity
|
||||
public class Phone {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private long id;
|
||||
|
||||
private String number;
|
||||
|
||||
@ManyToOne
|
||||
private Employee employee;
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getNumber() {
|
||||
return number;
|
||||
}
|
||||
|
||||
public void setNumber(String number) {
|
||||
this.number = number;
|
||||
}
|
||||
|
||||
public Employee getEmployee() {
|
||||
return employee;
|
||||
}
|
||||
|
||||
public void setEmployee(Employee employee) {
|
||||
this.employee = employee;
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
spring.datasource.data=classpath:db/import_joins.sql
|
|
@ -0,0 +1,13 @@
|
|||
INSERT INTO department (id, name) VALUES (1, 'Infra');
|
||||
INSERT INTO department (id, name) VALUES (2, 'Accounting');
|
||||
INSERT INTO department (id, name) VALUES (3, 'Management');
|
||||
|
||||
INSERT INTO joins_employee (id, name, age, department_id) VALUES (1, 'Baeldung', '35', 1);
|
||||
INSERT INTO joins_employee (id, name, age, department_id) VALUES (2, 'John', '35', 2);
|
||||
INSERT INTO joins_employee (id, name, age, department_id) VALUES (3, 'Jane', '35', 2);
|
||||
|
||||
INSERT INTO phone (id, number, employee_id) VALUES (1, '111', 1);
|
||||
INSERT INTO phone (id, number, employee_id) VALUES (2, '222', 1);
|
||||
INSERT INTO phone (id, number, employee_id) VALUES (3, '333', 1);
|
||||
|
||||
COMMIT;
|
|
@ -0,0 +1,130 @@
|
|||
package com.baeldung.joins;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.baeldung.joins.model.Department;
|
||||
import com.baeldung.joins.model.Phone;
|
||||
import java.util.List;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import javax.persistence.TypedQuery;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
|
||||
import org.springframework.test.context.ActiveProfiles;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@DataJpaTest
|
||||
@ActiveProfiles("joins")
|
||||
public class JpaJoinsIntegrationTest {
|
||||
|
||||
@PersistenceContext
|
||||
private EntityManager entityManager;
|
||||
|
||||
@Test
|
||||
public void whenPathExpressionIsUsedForSingleValuedAssociation_thenCreatesImplicitInnerJoin() {
|
||||
TypedQuery<Department> query = entityManager.createQuery("SELECT e.department FROM Employee e", Department.class);
|
||||
|
||||
List<Department> resultList = query.getResultList();
|
||||
|
||||
assertThat(resultList).hasSize(3);
|
||||
assertThat(resultList).extracting("name")
|
||||
.containsOnly("Infra", "Accounting", "Accounting");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenJoinKeywordIsUsed_thenCreatesExplicitInnerJoin() {
|
||||
TypedQuery<Department> query = entityManager.createQuery("SELECT d FROM Employee e JOIN e.department d", Department.class);
|
||||
|
||||
List<Department> resultList = query.getResultList();
|
||||
|
||||
assertThat(resultList).hasSize(3);
|
||||
assertThat(resultList).extracting("name")
|
||||
.containsOnly("Infra", "Accounting", "Accounting");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenInnerJoinKeywordIsUsed_thenCreatesExplicitInnerJoin() {
|
||||
TypedQuery<Department> query = entityManager.createQuery("SELECT d FROM Employee e INNER JOIN e.department d", Department.class);
|
||||
|
||||
List<Department> resultList = query.getResultList();
|
||||
|
||||
assertThat(resultList).hasSize(3);
|
||||
assertThat(resultList).extracting("name")
|
||||
.containsOnly("Infra", "Accounting", "Accounting");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenEntitiesAreListedInFromAndMatchedInWhere_ThenCreatesJoin() {
|
||||
TypedQuery<Department> query = entityManager.createQuery("SELECT d FROM Employee e, Department d WHERE e.department = d", Department.class);
|
||||
|
||||
List<Department> resultList = query.getResultList();
|
||||
|
||||
assertThat(resultList).hasSize(3);
|
||||
assertThat(resultList).extracting("name")
|
||||
.containsOnly("Infra", "Accounting", "Accounting");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenEntitiesAreListedInFrom_ThenCreatesCartesianProduct() {
|
||||
TypedQuery<Department> query = entityManager.createQuery("SELECT d FROM Employee e, Department d", Department.class);
|
||||
|
||||
List<Department> resultList = query.getResultList();
|
||||
|
||||
assertThat(resultList).hasSize(9);
|
||||
assertThat(resultList).extracting("name")
|
||||
.containsOnly("Infra", "Accounting", "Management", "Infra", "Accounting", "Management", "Infra", "Accounting", "Management");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenCollectionValuedAssociationIsJoined_ThenCanSelect() {
|
||||
TypedQuery<Phone> query = entityManager.createQuery("SELECT ph FROM Employee e JOIN e.phones ph ", Phone.class);
|
||||
|
||||
List<Phone> resultList = query.getResultList();
|
||||
|
||||
assertThat(resultList).hasSize(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenMultipleEntitiesAreListedWithJoin_ThenCreatesMultipleJoins() {
|
||||
TypedQuery<Phone> query = entityManager.createQuery("SELECT ph FROM Employee e JOIN e.department d JOIN e.phones ph WHERE d.name IS NOT NULL", Phone.class);
|
||||
|
||||
List<Phone> resultList = query.getResultList();
|
||||
|
||||
assertThat(resultList).hasSize(3);
|
||||
assertThat(resultList).extracting("number")
|
||||
.containsOnly("111", "222", "333");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenLeftKeywordIsSpecified_thenCreatesOuterJoinAndIncludesNonMatched() {
|
||||
TypedQuery<Department> query = entityManager.createQuery("SELECT DISTINCT d FROM Department d LEFT JOIN d.employees e", Department.class);
|
||||
|
||||
List<Department> resultList = query.getResultList();
|
||||
|
||||
assertThat(resultList).hasSize(3);
|
||||
assertThat(resultList).extracting("name")
|
||||
.containsOnly("Infra", "Accounting", "Management");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenFetchKeywordIsSpecified_ThenCreatesFetchJoin() {
|
||||
TypedQuery<Department> query = entityManager.createQuery("SELECT d FROM Department d JOIN FETCH d.employees", Department.class);
|
||||
|
||||
List<Department> resultList = query.getResultList();
|
||||
|
||||
assertThat(resultList).hasSize(3);
|
||||
assertThat(resultList).extracting("name")
|
||||
.containsOnly("Infra", "Accounting", "Accounting");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void whenLeftAndFetchKeywordsAreSpecified_ThenCreatesOuterFetchJoin() {
|
||||
TypedQuery<Department> query = entityManager.createQuery("SELECT d FROM Department d LEFT JOIN FETCH d.employees", Department.class);
|
||||
List<Department> resultList = query.getResultList();
|
||||
assertThat(resultList).hasSize(4);
|
||||
assertThat(resultList).extracting("name")
|
||||
.containsOnly("Infra", "Accounting", "Accounting", "Management");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue