2020年5月2日 星期六

使用Criteria API基礎查詢


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

JPA對資料庫的存取除了使用JPQL之外,還可以使用Criteria APICriteria API的大致使用方式已經在前一章節說明,本章重點在資料庫存取情境的因應和與JPQL的比較,原則上將與第3章的各範例程式合併,因此內容編排不再贅述Entity物件的保存(persist)與建構(construct)方式。
以下範例介紹SELECT子句內為單一欄位或複數欄位的作法。
查詢單一欄位
Entity類別Employee為例JPQL查詢其單一欄位name時使用指令為:
  1. SELECT e.name FROM Employee e
以下為使用Criteria API的作法:
  1. @Test
  2. public void criteria_SelectSingle() {
  3. EntityManager em = emf.createEntityManager();
  4. CriteriaBuilder cb = em.getCriteriaBuilder();
  5. CriteriaQuery sql = cb.createQuery(String.class);
  6. Root emp = sql.from(Employee.class);
  7. Path name = emp.get("name");
  8. sql.select(name);
  9. TypedQuery typedQuery = em.createQuery(sql);
  10. List resultList = typedQuery.getResultList();
  11. resultList.forEach(System.out::println);
  12. em.close();
  13. assertThat(resultList, hasSize(3));
  14. }
【說明】
5
CriteriaQuery指定要回傳的資料型態,欄位name的型態為String
7-8
CriteriaQueryselect()方法接受Expression型態的物件,Path為其子型態,也可以使用Expression<String>宣告變數。
查詢複數欄位
Entity類別Employee為例JPQL查詢欄位idname時使用指令為:
  1. SELECT e.id, e.name FROM Employee e
以下範例行7與行8為使用Criteria API的作法。因為CriteriaBuilder的方法array()接受「可變動個數參數(varargs)」,且介面Selection是介面Expression的父型態,因此方法參數可接受個數變動的Expression物件:
  1. CompoundSelection array(Selection... elections);
  1. @Test
  2. public void criteria_SelectArray() {
  3. EntityManager em = emf.createEntityManager();
  4. CriteriaBuilder cb = em.getCriteriaBuilder();
  5. CriteriaQuery sql = cb.createQuery(Object[].class);
  6. Root emp = sql.from(Employee.class);
  7. sql.select(cb.array(emp.get("id"),
  8. emp.get(Employee_.name)));
  9. TypedQuery typedQuery = em.createQuery(sql);
  10. List resultList = typedQuery.getResultList();
  11. resultList.forEach(arr -> System.out.println(Arrays.toString(arr)));
  12. em.close();
  13. assertThat(resultList, hasSize(3));
  14. }

說明
5
CriteriaQuery指定查詢後得到的資料型態,可使用Object[]同時將欄位id, name的資料封裝。
7-8
CriteriaQueryselect()方法接受多個Expression型態的物件。
7
欄位名稱使用String描述。
8
欄位名稱使用metamodel類別Employee1_的靜態欄位name描述。
另外一個查詢複數欄位的作法為使用CriteriaQuery的multiselect()方法,如以下範例行7。因為方法multiselect()接受可變動個數參數,且介面Selection是介面Expression的父型態,因此方法參數可接受個數變動的Expression物件:
  1. CriteriaQuery multiselect(Selection... elections);
此時不需要使用CriteriaBuilder的array()方法結合欄位,直接列舉即可:
  1. @Test
  2. public void criteria_MultiSelect() {
  3. EntityManager em = emf.createEntityManager();
  4. CriteriaBuilder cb = em.getCriteriaBuilder();
  5. CriteriaQuery sql = cb.createQuery(Object[].class);
  6. Root emp = sql.from(Employee.class);
  7. sql.multiselect(emp.get(Employee_.id), emp.get(Employee_.name));
  8. TypedQuery typedQuery = em.createQuery(sql);
  9. List resultList = typedQuery.getResultList();
  10. resultList.forEach(arr -> System.out.println(Arrays.toString(arr)));
  11. em.close();
  12. assertThat(resultList, hasSize(3));
  13. }

沒有留言:

張貼留言