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時使用指令為:
SELECT e.name FROM Employee e
以下為使用Criteria API的作法:
@Test
public void criteria_SelectSingle() {
    EntityManager em = emf.createEntityManager();
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery sql = cb.createQuery(String.class);
    Root emp = sql.from(Employee.class);
    Path name = emp.get("name");
    sql.select(name);
    TypedQuery typedQuery = em.createQuery(sql);
    List resultList = typedQuery.getResultList();
    resultList.forEach(System.out::println);
    em.close();
    assertThat(resultList, hasSize(3));
}
【說明】
5
CriteriaQuery指定要回傳的資料型態,欄位name的型態為String
7-8
CriteriaQueryselect()方法接受Expression型態的物件,Path為其子型態,也可以使用Expression<String>宣告變數。
查詢複數欄位
Entity類別Employee為例JPQL查詢欄位idname時使用指令為:
SELECT e.id, e.name FROM Employee e
以下範例行7與行8為使用Criteria API的作法。因為CriteriaBuilder的方法array()接受「可變動個數參數(varargs)」,且介面Selection是介面Expression的父型態,因此方法參數可接受個數變動的Expression物件:
CompoundSelection array(Selection... elections);
@Test 
public void criteria_SelectArray() {
    EntityManager em = emf.createEntityManager();
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery sql = cb.createQuery(Object[].class);
    Root emp = sql.from(Employee.class);
    sql.select(cb.array(emp.get("id"), 
                         emp.get(Employee_.name)));
    TypedQuery typedQuery = em.createQuery(sql);
    List resultList = typedQuery.getResultList();
    resultList.forEach(arr -> System.out.println(Arrays.toString(arr)));
    em.close();
    assertThat(resultList, hasSize(3));
}

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

沒有留言:

張貼留言