2013-01-20 59 views
3

我有兩個實體Customer和Order以一對多的關係。 對於每位客戶,我需要統計相關訂單的數量並按照該數字對結果進行排序。 在本地Postgres的查詢它看起來像這樣:JPA CriteriaBuilder - 根據一對多關係中關聯實體的數量排序

select cust.id, count(order.id) from customers cust 
left outer join orders order 
on cust.id = order.customer_id 
where .... conditions ... 
group by cust.id 
order by count desc; 

但由於該查詢是使用CriteriaBuilder擺在附加條件一塊較大的代碼的一部分,我必須做到這一點使用CriteriaBuilder。在Hibernate中,我可能會使用Projections,但在JPA中找不到類似的東西。

任何使用CriteraBuilder編寫查詢的幫助將不勝感激。

預先感謝您。

+0

看看一個很好的教程。我個人建議[這一個](http://www.ibm.com/developerworks/java/library/j-typesafejpa/) – perissf

回答

6

假設實體客戶有OneToMany屬性是這樣的:

@OneToMany(mappedBy = "customerId") 
private Collection<Order> orders; 

您可以使用下面的查詢:

EntityManager em; // to be built or injected 
CriteriaBuilder cb = em.getCriteriaBuilder(); 
CriteriaQuery<Tuple> cq = cb.createTupleQuery(); 
Root<Customer> customer = cq.from(Customer.class); 
CollectionJoin<Customer, Order> orders = customer.join(Customer_.orders, JoinType.LEFT); 
cq.select(cb.tuple(customer, cb.count(orders))); 
cq.where(... add some predicates here ...); 
cq.groupBy(customer.get(Customer_.id)); 
cq.orderBy(cb.desc(cb.count(orders))); 
List<Tuple> result = em.createQuery(cq).getResultList(); 
for (Tuple t : result) { 
    Customer c = (Customer) t.get(0); 
    Long cnt = (Long) t.get(1); 
    System.out.println("Customer " + c.getName() + " has " + cnt + " orders"); 
} 

上述方法使用Metamodel。如果您不喜歡它,您可以用"orders"Customer_.id替換Customer_.orders"id"

如果OneToMany屬性是另一種類型的,用適當的類型(ListJoinSetJoinMapJoin)的集合取代CollectionJoin

+0

謝謝你的答案。不幸的是,它並不適用於我的情況 - 原因是我試圖整合我的代碼是如此的結構化,以至於它使用'SimpleJpaRepository'中的'findAll(規範 spec,Pageable pageable)' - 傳入'Pageable'對象也必須包含按列排序。如果我沒有指定在[PageRequest(int page,int size,Sort sort)中進行排序的列,但是通過CriteariaBuilder按照上面的建議進行排序 - 它只是假定排序爲空並覆蓋了我指定的任何順序在CriteriaBuilder中。 – Alex

+0

我不明白,你能澄清嗎?然而這似乎是一個完全不同的問題。我建議打開一個新的標記,如果它回答了原來的問題,這看起來確實如此。 – perissf

+0

這發生在'SimpleJpaRepository',第417行:'query.orderBy(toOrders(pageable.getSort(),root,builder));'。我正在檢查Spring數據源以找到一種方法來使它與Pageable協同工作,並且不會覆蓋我在CriteriaBuilder中指定的順序。如果你能夠進一步提醒我,我會非常感激。雖然我知道你已經幫了我很多。謝謝。 – Alex