JPA CriteriaBuilder – 按一对多关系中的关联实体数量排序

我有两个实体Customer和Order,一对多关系。 对于每个客户,我需要计算相关订单的数量,并按此数字对结果进行排序。 在本机postgres查询中,它看起来像这样:

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编写查询的帮助都将非常感激。

先谢谢你。

假设实体Customer有这样的OneToMany属性:

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

您可以使用以下查询:

 EntityManager em; // to be built or injected CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery cq = cb.createTupleQuery(); Root customer = cq.from(Customer.class); CollectionJoin 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 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 。 如果您不喜欢它,可以将Customer_.orders替换为"orders" ,将Customer_.id替换为"id"

如果OneToMany属性是另一种类型,则将CollectionJoin替换为正确类型的集合( ListJoinSetJoinMapJoin )。