本文為【Spring Boot情境式網站開發指南:使用Spring Data JPA、Spring Security、Spring Web Flow】一書的【 第4章 Criteria API入門】延續,完整範例程式碼可至出版社下載
- Root<Entity>使用join()方法和Map<Key, Value>屬性欄位聯結後,可以取得MapJoin<Entity, Key, Value>物件。
- MapJoin<Entity, Key, Value>具備以下方法存取關連到Map型態的欄位:
當JPQL使用以下查詢時:
- key():取得Map物件的key值,等同JPQL的KEY敘述。
- value():取得Map物件的value值,等同JPQL的VALUE敘述。
- entry():同時取得Map物件的key與value值,等同JPQL的ENTRY敘述。
對應的Criteria API用法如下:
- TypedQuery
typedQuery = em.createQuery( "SELECT c.name, KEY(map), VALUE(map) FROM Customer c JOIN c.itemQtyMap map", Tuple.class);
- @Test
- public void Criteria_GetMapKeyValueByTuple() {
- EntityManager em = emf.createEntityManager();
- CriteriaBuilder cb = em.getCriteriaBuilder();
- CriteriaQuery
sql = cb.createTupleQuery(); Root cust = sql.from(Customer.class); MapJoin itemQtyMap = cust.join(Customer_.itemQtyMap); sql.multiselect(cust.get(Customer_.name), itemQtyMap.key(), itemQtyMap.value() ); TypedQuery typedQuery = em.createQuery(sql); List resultList = typedQuery.getResultList(); List stringList = resultList.stream() .map(t -> t.get(0) + ", " + t.get(1) + ", " + t.get(2)) .collect(Collectors.toList()); stringList.forEach(System.out::println); assertThat(stringList, containsInAnyOrder("jim, computer, 1", "jim, mouse, 4", "colin, notebook, 3")); }
- 行5
使用Tuple封裝查詢結果的複數欄位。
- 行7-8
使用Root<Customer> cust的join()方法聯結Map型態的欄位,並回傳MapJoin<Customer, String, Integer>物件。介面MapJoin<1, 2, 3>的泛型指定3種型態:
1. Entity型態,本例為Customer。
2. Map欄位的key型態,本例為String。
3. Map欄位的value型態,本例為Integer。
- 行9-11
使用CriteriaBuilder物件的multiselect()方法查詢name欄位, Map欄位的key欄位由itemQtyMap.key()表示,Map欄位的value欄位由itemQtyMap.value()表示。當JPQL使用以下查詢時:
- TypedQuery
對應的Criteria API用法如下。本例只查詢Map的key與value等2個欄位,使用Map.Entry型態封裝查詢後的結果:
- @Test
- public void Criteria_GetEntryByMapEntry() {
- EntityManager em = emf.createEntityManager();
- CriteriaBuilder cb = em.getCriteriaBuilder();
- CriteriaQuery
// hibernate.version=5.2.10.Final will throw ClassCastException List resultList = typedQuery.getResultList(); List stringList = resultList.stream() .map(entry -> entry.getKey()+ ", " + entry.getValue()) .collect(Collectors.toList()); stringList.forEach(System.out::println); assertThat(stringList, containsInAnyOrder("computer, 1", "mouse, 4", "notebook, 3")); }
- 行5
使用Map.Entry封裝查詢後的Map的key與value欄位。
- 行9-11
使用CriteriaBuilder物件的select()方法查詢itemQtyMap.entry(),將同時取得key與value欄位。值得注意的是,本例在5.2.10.Final的hibernate版本下將拋出ClassCastException的例外,使用較新版本則無此問題。
沒有留言:
張貼留言