2020年7月19日 星期日

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

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

使用CriteriaBuilder的isMember()方法和isNotMember()方法決定關聯的「集合物件」內是否有特定成員。以isMember()為例:
【語法】
<E, C extends Collection<E>>
 Predicate isMember(Expression<E> elem, Expression<C> collection);
泛型E:代表集合物件成員型態。
泛型C:代表集合物件型態。
回傳型態Predicate。
方法參數:
1. Expression<E> elem:型態為E的Expression物件參考,輸入成員物件。
2. Expression<C> collection:型態為C的Expression物件參考,輸入集合物件欄位物件。

使用 MEMBER OF 

當JPQL使用以下查詢時:
SELECT e FROM Employee e WHERE '777' MEMBER OF e.phoneNumbers
對應的Criteria API用法如下:
@Test
public void Criteria_MemberOf() {
  EntityManager em = emf.createEntityManager();
  CriteriaBuilder cb = em.getCriteriaBuilder();
  CriteriaQuery sql = cb.createQuery(Employee.class);
  Root emp = sql.from(Employee.class);
  sql.select(emp)
    .where(cb.isMember(cb.literal("777"), emp.get(Employee_.phoneNumbers)));
  TypedQuery typedQuery = em.createQuery(sql);
  List resultList = typedQuery.getResultList();
  resultList.forEach(System.out::println);
  em.close();
  //assertThat(resultList, IsEmptyCollection.empty());
  assertThat(resultList, containsInAnyOrder(employee1, employee3));
  assertThat(resultList, hasSize(2));
}
行8:
查詢欄位Employee_.phoneNumbers內含字串777者。藉由CriteriaBuilder 的literal()方法將String轉換為Expression<String>。

使用 NOT MEMBER OF 

當JPQL使用以下查詢時:
SELECT e FROM Employee e WHERE '777' NOT MEMBER OF e.phoneNumbers
對應的Criteria API用法如下:
@Test 
public void Criteria_NotMemberOf() {
  EntityManager em = emf.createEntityManager();
  CriteriaBuilder cb = em.getCriteriaBuilder();
  CriteriaQuery sql = cb.createQuery(Employee.class);
  Root emp = sql.from(Employee.class);
  sql.select(emp)
      .where(cb.isNotMember("777", emp.get(Employee_.phoneNumbers)));
  TypedQuery typedQuery = em.createQuery(sql);
  List resultList = typedQuery.getResultList();
  resultList.forEach(System.out::println);
  em.close();
  assertThat(resultList, containsInAnyOrder(employee2, employee4));
  assertThat(resultList, hasSize(2));
}
行8:
使用CriteriaBuilder的isNotMember()方法。第1個參數直接使用String型態,此為Expression<String>的overloading版本。
方法isMember()或isNotMember()的第1個參數也可以是另一個「一般型態」的欄位。當JPQL使用以下查詢時:
SELECT e FROM Employee e 
    WHERE e.primaryPhoneNumber 
            NOT MEMBER OF e.phoneNumbers
對應的Criteria API用法如下,注意行8程式碼:
@Test
public void Criteria_NotMemberOf2() {
  EntityManager em = emf.createEntityManager();
  CriteriaBuilder cb = em.getCriteriaBuilder();
  CriteriaQuery sql = cb.createQuery(Employee.class);
  Root emp = sql.from(Employee.class);
  sql.select(emp)
      .where(cb.isNotMember(emp.get(Employee_.primaryPhoneNumber),
                            emp.get(Employee_.phoneNumbers)));
  TypedQuery typedQuery = em.createQuery(sql);
  List resultList = typedQuery.getResultList();
  resultList.forEach(System.out::println);
  em.close();
  assertThat(resultList, containsInAnyOrder(employee4, employee2));
  assertThat(resultList, hasSize(2));
}

沒有留言:

張貼留言