[英]Ordering results of a JPA CriteriaQuery by MAX(childitem.property)
我试图找到一种使用子对象集合的第一个属性而不是对象本身对JPA条件查询的结果进行排序的优雅方法。 例如:
@Entity
class Parent {
protected Set<Child> children;
}
@Entity
class Child {
protected Date timestamp;
}
父母可以有几个孩子,每个孩子都有不同的时间戳。
我希望能够添加到现有的JPA CriteriaQuery / TypedQuery中,以便按MAX(child.timestamp)对Parent对象的列表进行排序,因此具有最新子时间戳的父项会首先出现。
我的通用条件构建器实现是这样的:
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(daoClass);
Root<T> queryRoot = criteriaQuery.from(daoClass);
// add wheres
Predicate filters = createPredicate(criteriaQuery, queryRoot, criteriaBuilder);
// filters = criteriaBuilder.and( /* lots of Predicate filter objects */ );
criteriaQuery.where(filters);
// add sorts
criteriaQuery.orderBy(createOrders(queryRoot, criteriaBuilder));
// <-- Ideally somewhere here add the new ordering
TypedQuery<T> typedQuery = em.createQuery(criteriaQuery);
希望有一个解决方案,不会破坏太多。
谢谢你的帮助。
编辑:在查询中收集的父数据是分页的,因此我无法对查询结果进行排序。 它必须是我构建的JPA查询的一部分。
你不能
@Entity
class Parent {
@OrderBy("timestamp DESC")
protected Set<Child> children;
}
我遇到了同样的情况。
对于您的特定情况,诀窍是不要在按订单排序之前添加过滤器。 Criteria API稍后将以正确的顺序排列。
所以它应该看起来像这样:
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery(daoClass);
Root<T> queryRoot = criteriaQuery.from(daoClass);
// get filters
Predicate filters = createPredicate(criteriaQuery, queryRoot, criteriaBuilder);
// filters = criteriaBuilder.and( /* lots of Predicate filter objects */ );
//This has to be a Boolean object (not primitive) so that it passes the reference to the object to your createOrders method and not the value.
Boolean filtersAdded = Boolean.FALSE;
// add sorts - send filters as a parameter
criteriaQuery.orderBy(createOrders(filters, filtersAdded, queryRoot, criteriaBuilder));
if (Boolean.FALSE.equals(filtersAdded)) {
criteriaQuery.where(filters);
}
TypedQuery<T> typedQuery = em.createQuery(criteriaQuery);
在createOrders
方法中,如果必须在条件中添加一个子查询( JPA CriteriaQuery Order By Latest Child属性 ),则还添加过滤器。 像这样:
criteriaQuery.where(subQueryCondition, filters));
filtersAdded = Boolean.TRUE;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.