3

我有两个实体 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 编写查询的任何帮助。

先感谢您。

4

2 回答 2

10

假设实体 Customer 具有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)。

于 2013-01-20T16:10:07.170 回答
1

在规范中使用它

cq.orderBy(cb.desc(cb.count(orders)));

还送PageRequest(1, 10, Sort.unsorted())。我就是这样做的。如果您将排序值作为未排序传递,然后使用您自己对连接实体的排序逻辑覆盖条件查询

于 2021-05-18T17:13:55.350 回答