2020年5月15日 星期五

INNER JOIN

使用INNER JOIN且未限定條件

當JPQL使用以下語句時:
  1. SELECT DISTINCT e FROM Employee e
  2. INNER JOIN e.tasks t
對應的Criteria API用法如下:
  1. public void Criteria_InnnerJoin() {
  2. EntityManager em = emf.createEntityManager();
  3. CriteriaBuilder cb = em.getCriteriaBuilder();
  4. CriteriaQuery sql = cb.createQuery(Employee.class);
  5. Root emp = sql.from(Employee.class);
  6. emp.join(Employee_.tasks);
  7. sql.select(emp)
  8. .distinct(true);
  9. TypedQuery typedQuery = em.createQuery(sql);
  10. List resultList = typedQuery.getResultList();
  11. resultList.forEach(System.out::println);
  12. em.close();
  13. assertThat(resultList, containsInAnyOrder(employee1, employee2, employee3));
  14. assertThat(resultList, hasSize(3));
  15. }
說明
  • 行6:
emp.join(Employee_.tasks); 等價於Employee e INNER JOIN e.tasks t

使用INNER JOIN並限定條件

承前例,但JPQL增加Task欄位值的限定條件:
  1. SELECT DISTINCT e FROM Employee e
  2. INNER JOIN e.tasks t
  3. WHERE t.name='Denise'
對應的Criteria API用法如下:
  1. @Test
  2. public void Criteria_InnerJoinWhere1() {
  3. EntityManager em = emf.createEntityManager();
  4. CriteriaBuilder cb = em.getCriteriaBuilder();
  5. CriteriaQuery sql = cb.createQuery(Employee.class);
  6. Root emp = sql.from(Employee.class);
  7. Join task = emp.join(Employee_.tasks);
  8. sql.select(emp)
  9. .where(cb.equal(task.get(Task_.name), "Denise"))
  10. .distinct(true);
  11. TypedQuery typedQuery = em.createQuery(sql);
  12. List resultList = typedQuery.getResultList();
  13. resultList.forEach(System.out::println);
  14. em.close();
  15. assertThat(resultList, containsInAnyOrder(employee1, employee3));
  16. assertThat(resultList, hasSize(2));
  17. }
說明:
  • 行7:
因WHERE子句需要INNER JOIN的表格的欄位加以限制條件,因此需要使用變數Join<Employee, Task> task承接Root<Employee>呼叫join()方法後回傳的物件。相似於Root<Employee>,但用Join<Employee, Task>;變數名稱慣例上使用第2個泛型型態Task來命名,本例為「task」。
若需要連續JOIN數個表格,如Entity類別A需要JOIN類別B與C,則依此類推:
Root<A> a = sql.from(A.class);
Join<A, C> c = a.join(A_.b).join(B_.c);
  • 行9:
where(cb.equal(task.get(Task_.name), "Denise"))等價於「WHERE t.name='Denise'」

使用INNER JOIN並指定2表格結合的欄位

承前例,但JPQL條件限定為跨2個表格的欄位必須相等:
  1. SELECT DISTINCT e FROM Employee e
  2. INNER JOIN e.tasks t
  3. WHERE t.name = e.name
對應的Criteria API用法如下:
  1. @Test
  2. public void Criteria_InnerJoinWhere2() {
  3. EntityManager em = emf.createEntityManager();
  4. CriteriaBuilder cb = em.getCriteriaBuilder();
  5. CriteriaQuery sql = cb.createQuery(Employee.class);
  6. Root emp = sql.from(Employee.class);
  7. ListJoin task = emp.join(Employee_.tasks);
  8. sql.select(emp)
  9. .where( cb.equal( task.get(Task_.name), emp.get(Employee_.name) ) );
  10. TypedQuery typedQuery = em.createQuery(sql);
  11. List resultList = typedQuery.getResultList();
  12. resultList.forEach(System.out::println);
  13. em.close();
  14. assertThat(resultList, containsInAnyOrder(employee2));
  15. assertThat(resultList, hasSize(1));
  16. }
說明:
  • 行9:
where( cb.equal( task.get(Task_.name), emp.get(Employee_.name) ) );等價於「WHERE t.name = e.name」

沒有留言:

張貼留言