2020年7月19日 星期日

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


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

使用LIKE搭配萬用字元「_」查詢
當JPQL使用以下查詢時:

  1. SELECT e FROM Employee e WHERE e.salary LIKE '_500.0'
對應的Criteria API用法如下:
  1. @Test
  2. public void Criteria_Like1() {
  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. sql.select(emp)
  8. .where( cb.like( emp.get(Employee_.salary).as(String.class), "_500.0" ) );
  9. List resultList = em.createQuery(sql).getResultList();
  10. resultList.forEach(System.out::println);
  11. em.close();
  12. assertThat(resultList, containsInAnyOrder(employee4));
  13. assertThat(resultList, hasSize(1));
  14. }
行8:
使用CriteriaBuilder的like()方法,第2個欄位指定like的樣式,第1個參數指定欄位。本例因為salary欄位是數字,要樣式比對必須是字串欄位:Predicate like(Expression<String> x, String pattern);因此使用as(String.class)方法將salary數字欄位值轉換為字串:emp.get(Employee_.salary).as(String.class)

使用LIKE搭配萬用字元「%」查詢

當JPQL使用以下查詢時:
  1. SELECT e FROM Employee e WHERE e.name LIKE 'J%'
對應的Criteria API用法如下:
  1. @Test
  2. public void Criteria_Like2() {
  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. sql.select(emp)
  8. .where( cb.like( emp.get(Employee_.name), "J%" ) );
  9. List resultList = em.createQuery(sql).getResultList();
  10. resultList.forEach(System.out::println);
  11. em.close();
  12. assertThat(resultList, containsInAnyOrder(employee1));
  13. assertThat(resultList, hasSize(1));
  14. }

使用NOT LIKE搭配命名變數查詢

當JPQL使用以下查詢時:
  1. SELECT e FROM Employee e WHERE e.name NOT LIKE :nameStartsWith
對應的Criteria API用法如下:
  1. @Test
  2. public void Criteria_NotLikeNamedParams() {
  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 nameParam =
  8. cb.parameter(String.class, "nameStartsWith");
  9. sql.select(emp)
  10. .where( cb.notLike(emp.get(Employee_.name), nameParam) );
  11. // .where( cb.like(emp.get(Employee_.name), nameParam).not() );
  12. TypedQuery typedQuery = em.createQuery(sql);
  13. typedQuery.setParameter("nameStartsWith", "J%");
  14. List resultList = typedQuery.getResultList();
  15. resultList.forEach(System.out::println);
  16. em.close();
  17. assertThat(resultList, containsInAnyOrder(employee2, employee3, employee4));
  18. assertThat(resultList, hasSize(3));
  19. }
行7-8:
以ParameterExpression< String >建立欄位name的命名變數物件參考「nameParam」,其名稱為「nameStartsWith」。
行10:
使用CriteriaBuilder的notLike()方法。欄位emp.get(Employee_.name)的限定條件為notLike (nameParam);
行11:
也可以使用CriteriaBuilder的like()方法,並在結尾加上not()。
行13:
以TypedQuery的setParameter()方法指定命名變數nameStartsWith並傳入字串樣式"J%"作為參數值。

使用LIKE並以ESCAPE跳脫萬用字元「_」查詢

當JPQL使用以下查詢時:
  1. SELECT e FROM Employee e WHERE e.dept LIKE '%@_%' ESCAPE '@'

對應的Criteria API用法如下:
  1. @Test
  2. public void Criteria_LikeEscape() {
  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. sql.select(emp)
  8. .where(cb.like(emp.get(Employee_.dept), "%@_%", '@'));
  9. List resultList = em.createQuery(sql).getResultList();
  10. resultList.forEach(System.out::println);
  11. em.close();
  12. assertThat(resultList, containsInAnyOrder(employee4));
  13. assertThat(resultList, hasSize(1));
  14. }
行8:
使用CriteriaBuilder的like()方法,因第2個參數要比對的是like樣式內的特殊字元「_」,因此由最後參數定義使用的跳脫字元:Predicate like(Expression<String> x, String pattern, char escapeChar);本例為「@」:cb.like( emp.get(Employee_.dept), "%@_%", '@' );

沒有留言:

張貼留言