我有两个实体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编写查询的任何帮助。
提前谢谢。
答案 0 :(得分:7)
假设客户实体拥有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。如果您不喜欢,可以将Customer_.orders
替换为"orders"
,将Customer_.id
替换为"id"
。
如果OneToMany
属性属于其他类型,请将CollectionJoin
替换为正确类型的集合(ListJoin
,SetJoin
,MapJoin
)。< / p>
答案 1 :(得分:0)
在规范中使用它
cq.orderBy(cb.desc(cb.count(orders)));
同时发送PageRequest(1, 10, Sort.unsorted())
。我就是这样做的。
如果您将 Sort 值作为 unsorted 传递,然后使用您自己的对加入的实体进行排序的逻辑覆盖标准查询