2020年5月8日 星期五

DISTINCT

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

SQL的DISTINCT用來得到成員不重複的集合物件,因此成員類別必須覆寫hashCode()與equals()方法。

使用DISTINCT取出Entity物件的字串成員

使用以下JPQL查詢時:
SELECT DISTINCT e.dept FROM Employee e
等價於使用以下Criteria API查詢。因為只查詢一個欄位dept,行7使用CriteriaQuery的distinct(true)方法只會針對該欄位過濾重複值:
@Test
public void Criteria_DistinctColumn() {
    EntityManager em = emf.createEntityManager();
    CriteriaQuery sql = em.getCriteriaBuilder().createQuery(String.class);
    Root emp = sql.from(Employee.class);
    sql.select(emp.get(Employee_.dept))
        .distinct(true);
    TypedQuery typedQuery = em.createQuery(sql);
    List resultList = typedQuery.getResultList();
    resultList.forEach(System.out::println);
    assertThat(resultList, contains("IT", "Admin"));
}

使用DISTINCT查詢多欄位

使用以下JPQL查詢時:
SELECT DISTINCT e.dept, e.salary FROM Employee e
ORDER BY e.dept ASC, e.salary DESC
等價於使用以下Criteria API查詢。多欄位的結果使用Object[ ]呈現:
@Test
public void Criteria_DistinctMultiColumns() {
    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_.dept), 
                  emp.get(Employee_.salary))
        .orderBy(cb.asc(emp.get(Employee_.dept)), 
                 cb.desc(emp.get(Employee_.salary)))
        .distinct(true);
    TypedQuery tq = em.createQuery(sql);
    List resultList = tq.getResultList();
    List stringList = resultList.stream()
            .map(arr -> Arrays.toString(arr)).collect(Collectors.toList());
    stringList.forEach(System.out::println);
    assertThat(stringList, contains("[Admin, 3500.0]", 
                                    "[IT, 2500.0]", 
                                    "[IT, 2000.0]"));
}

沒有留言:

張貼留言