2020年5月8日 星期五

DISTINCT

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

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

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

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

使用DISTINCT查詢多欄位

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

沒有留言:

張貼留言