在JPA 2 Criteria API中使用SELECT DISTINCT + ORDER BY。

14
我有一个类 Lawsuit,它包含一个List<Hearing>,每个Hearing都有一个Date属性。
我需要按照Hearing的日期顺序选择所有的Lawsuit。 我有一个如下的CriteriaQuery:
CriteriaBuilder           cb = em.getCriteriaBuilder();
CriteriaQuery<Lawsuit>    cq = cb.createQuery(Lawsuit.class);
Root<Lawsuit>           root = cq.from(Lawsuit.class);

我使用distinct来压缩结果:

cq.select(root).distinct(true);

我随后参加LawsuitHearing

Join<Lawsuit, Hearing> hearing = root.join("hearings", JoinType.INNER);
创建 Predicate
predicateList.add(cb.isNotNull(hearing.<Date>get("date")));

以及 订单

orderList.add(cb.asc(hearing.<Date>get("date")));

如果我避免使用 distinct,一切都正常,但是如果我使用它,就会出现以下错误:它抱怨无法根据未在 SELECT 中的字段排序:

Caused by: org.postgresql.util.PSQLException: ERROR: for SELECT DISTINCT, ORDER BY expressions must appear in select list

List<Hearing> 已经可以通过返回的 Lawsuit 类访问,所以我感到困惑:我应该如何将它们添加到选择列表中?


你需要为List<Hearing>添加一个子查询,然后在子查询中加入order by吗?我现在没有时间看它。 - K.Nicholas
谢谢@Nicholas;您如何使用Criteria API执行内部查询? - Andrea Ligios
这个答案可能会有所帮助。 - Dragan Bozanovic
我不使用 Criteria API,但在那里编写子查询应该很简单。 - Dragan Bozanovic
@DraganBozanovic:我同意,它应该可以实现,但是我不知道如何做到这一点(对于使用Criteria API选择的字段)。顺便说一下,我发现问题出在连接上(真是个笨蛋)。如果您能回答有关去重和连接的通用问题(不涉及Criteria API),我将授予您奖励。干杯 - Andrea Ligios
2个回答

6
我已经在其他地方找到了问题的根源,并解决了它,所以不需要按照问题中所要求的去做; 正如其他答案所描述的那样,在这里执行“distinct”应该是不必要的。
重复的行是由于错误的“left join”引起的,即使谓词没有被使用,也对集合(根对象的属性)执行了“left join”。
Join<Lawsuit, Witness> witnesses = root.join("witnesses", JoinType.LEFT);
if (witnessToFilterWith!=null) {
    predicateList.add(cb.equal(witnesses.<Long>get("id"),witnessToFilterWith.getId()));
}

应该明显以内联(inner)方式执行join,并且只有在需要时

if (witnessToFilterWith!=null) {
    Join<Lawsuit, Witness> witnesses = root.join("witnesses", JoinType.INNER);
    predicateList.add(cb.equal(witnesses.<Long>get("id"),witnessToFilterWith.getId()));
}

如果您因为遇到同样的问题而来到这里,在连接中搜索该问题


4
你还可以通过根表的主键列进行分组,从而进行去重:
 cq.groupBy(root.get("id")); // Assuming that Lawsuite.id is primary key column

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接