2020年7月19日 星期日

在WHERE敘述使用比較(Comparision)關鍵字:IN


本文為【Spring Boot情境式網站開發指南:使用Spring Data JPA、Spring Security、Spring Web Flow】一書的【 第4章 Criteria API入門】延續,完整範例程式碼可至出版社下載

【小標】BETWEEN數字區間
當JPQL使用以下查詢時:

  1. SELECT e FROM Employee e WHERE e.salary IN (2000.0, 3000.0, 4000.0)
對應的Criteria API用法如下:
  1. @Test
  2. public void Criteria_InExpression() {
  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. Expression salary = emp.get(Employee_.salary);
  8. Expression inExp = salary.in(2000.0, 3000.0, 4000.0);
  9. sql.select(emp).where(inExp);
  10. TypedQuery typedQuery = em.createQuery(sql);
  11. List resultList = typedQuery.getResultList();
  12. resultList.forEach(System.out::println);
  13. em.close();
  14. assertThat(resultList,
  15. containsInAnyOrder(employee1, employee2, employee3));
  16. assertThat(resultList, hasSize(3));
  17. }
行7: 
建立欄位表示式物件Expression<Double> salary = emp.get(Employee_.salary);
行8: 
呼叫Expression<Double>物件的in()方法,允許傳入個數變動的Double物件,本例為in(2000.0, 3000.0, 4000.0),並回傳Expression<Boolean>物件,將作為where()方法的輸入參數。

使用NOT IN於字面字串常量群組

當JPQL使用以下查詢時:
  1. SELECT e FROM Employee e WHERE e.name NOT IN ('Jim', 'Rose')
對應的Criteria API用法如下:
  1. public void Criteria_NotInExpression() {
  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. sql.select(emp) .where( emp.get(Employee_.name).in("Jim", "Rose").not() );
  7. TypedQuery typedQuery = em.createQuery(sql);
  8. List resultList = typedQuery.getResultList();
  9. resultList.forEach(System.out::println);
  10. em.close();
  11. assertThat(resultList, containsInAnyOrder(employee3, employee4));
  12. assertThat(resultList, hasSize(2));
  13. }
行6:
承前單元測試方法Criteria_InExpression(),本例不在刻意建立欄位表示式物件Expression<String>,與呼叫in()方法後回傳的Expression<Boolean>物件,直接將兩者合併傳入方法where()中:where( emp.get(Employee_.name).in("Jim", "Rose").not() );並在in()方法後再呼叫not()方法,表示否定:NOT IN。

使用IN於命名變數

當JPQL使用以下查詢時:
  1. Query query = em.createQuery(
  2. "SELECT e FROM Employee e WHERE e.dept IN :deptNames");
  3. query.setParameter("deptNames", Arrays.asList("IT", "Sales", "HR"));
對應的Criteria API用法如下:
  1. @Test
  2. public void Criteria_ParameterExpression() {
  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. ParameterExpression deptParam =
  8. cb.parameter(Collection.class, "deptNames");
  9. sql.select(emp) .where(emp.get(Employee_.dept).in(deptParam));
  10. TypedQuery typedQuery = em.createQuery(sql);
  11. typedQuery.setParameter("deptNames", Arrays.asList("IT", "Sales", "HR"));
  12. List resultList = typedQuery.getResultList();
  13. resultList.forEach(System.out::println);
  14. em.close();
  15. assertThat(resultList, containsInAnyOrder(employee1, employee2, employee4));
  16. assertThat(resultList, hasSize(3));
  17. }
【說明】
行7-8:
以ParameterExpression<Collection>建立欄位dept的命名變數物件參考「deptParam」,其名稱為「deptNames」,注意參數型態為Collection。
行9:
欄位emp.get(Employee_.dept)的限定條件為in(deptParam);

行11:
以TypedQuery的setParameter()方法指定命名變數deptNames並傳入Collection物件Arrays.asList("IT", "Sales", "HR")作為參數值。

沒有留言:

張貼留言