在JPA 2 Criteria API中选择DISTINCT + ORDER BY
我有一个类Lawsuit
,它包含一个List
,每个都有一个Date
属性。
我需要选择在Hearing
日期之前订购的所有Lawsuit
我有一个CriteriaQuery之类的
CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery cq = cb.createQuery(Lawsuit.class); Root root = cq.from(Lawsuit.class);
我使用distinct来展平结果:
cq.select(root).distinct(true);
然后我加入 Lawsuit
与Hearing
Join hearing = root.join("hearings", JoinType.INNER);
创建Predicate
predicateList.add(cb.isNotNull(hearing.get("date")));
和Order
s:
orderList.add(cb.asc(hearing.get("date")));
如果我避免使用它,一切正常,但如果我使用它,它会抱怨无法根据SELECT中没有的字段进行排序:
引起:org.postgresql.util.PSQLException:错误:对于
SELECT DISTINCT
,ORDER BY
表达式必须出现在选择列表中
List
已经可以通过返回的Lawsuit
类访问,所以我很困惑:我应该如何将它们添加到选择列表中?
我已经在其他地方发现了问题的根源,解决问题就没有必要去做问题中的问题; 如其他答案中所述,在这里执行distinct
应该是不必要的。
重复行是由对集合(根对象的属性)执行的错误left join
发起的,即使未使用谓词:
Join witnesses = root.join("witnesses", JoinType.LEFT); if (witnessToFilterWith!=null) { predicateList.add(cb.equal(witnesses.get("id"),witnessToFilterWith.getId())); }
显然, join
应该作为inner
执行,并且仅在需要时执行 :
if (witnessToFilterWith!=null) { Join witnesses = root.join("witnesses", JoinType.INNER); predicateList.add(cb.equal(witnesses.get("id"),witnessToFilterWith.getId())); }
所以,如果你在这里是因为你遇到了同样的问题,请在连接中搜索问题 。
您还可以根据根表的主键列通过组重复删除:
cq.groupBy(root.get("id")); // Assuming that Lawsuite.id is primary key column