我的spring-data存储库中有以下命名查询:
@Query("FROM Pedido p JOIN FETCH p.status ps WHERE ps.status IN (?1) AND ps.id IN (SELECT MAX(ps2.id) FROM PedidoStatus ps2 GROUP BY ps2.pedido)")
我正在尝试使用Criteria API和spring-data规范获得相同的结果,这是我到目前为止所做的:
public static Specification<Pedido> byUltimoStatus(final List<PedidoStatus.StatusPedido> ultimoStatus) {
return new Specification<Pedido>() {
public Predicate toPredicate(Root<Pedido> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
Expression<PedidoStatus.StatusPedido> status = root.join("status").get("status");
Predicate predicateByStatus = status.in(ultimoStatus);
final Subquery<Long> subQuery = query.subquery(Long.class);
final Root<PedidoStatus> ps = subQuery.from(PedidoStatus.class);
Expression<Long> psId= ps.get("id");
Expression<Long> maxId = builder.max(psId);
subQuery.select(maxId);
subQuery.groupBy(ps.get("pedido").get("id"));
Predicate predicateByUltimoStatus = builder.in(root.join("status").get("id")).value(subQuery);
return builder.and(predicateByStatus, predicateByUltimoStatus);
}
};}
它仍然不起作用,看起来有一个额外的
INNERJOIN PedidoStatus
在结果查询中。
这是@Query的结果:
select ... from Pedido pedido0_ inner join PedidoStatus status1_ on pedido0_.id=status1_.pedido where (status1_.status in (? , ?)) and (status1_.id in (select max(pedidostat2_.id) from PedidoStatus pedidostat2_ group by pedidostat2_.pedido))
这是Criteria API的结果:
select ... from Pedido pedido0_ inner join PedidoStatus status1_ on pedido0_.id=status1_.pedido inner join PedidoStatus status2_ on pedido0_.id=status2_.pedido where (pedido0_.id is not null) and status1_.status IN (?, ?) and (status2_.id in (select max(pedidostat3_.id) from PedidoStatus pedidostat3_ group by pedidostat3_.pedido))
答案 0 :(得分:0)
知道这是一个非常古老的问题,我认为在CriteriaQuery生成的查询中重复INNERJOIN的原因是构建查询的代码确实实际调用了root.join("status")
两次。第一次调用的结果应保存到局部变量中,因此您可以重复使用它,而不是连接两次。
首先你做:
Expression<PedidoStatus.StatusPedido> status = root.join("status").get("status");
以后你会这样做:
Predicate predicateByUltimoStatus = builder.in(root.join("status").get("id")).value(subQuery);