本文為【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敘述。
TypedQuery對應的Criteria API用法如下: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
- 行5
使用Map.Entry封裝查詢後的Map的key與value欄位。
- 行9-11
使用CriteriaBuilder物件的select()方法查詢itemQtyMap.entry(),將同時取得key與value欄位。值得注意的是,本例在5.2.10.Final的hibernate版本下將拋出ClassCastException的例外,使用較新版本則無此問題。
沒有留言:
張貼留言