通过MAX订购JPA CriteriaQuery的结果(childitem.property)

时间:2014-01-08 15:46:55

标签: java hibernate jpa criteria

我正在尝试使用第一个子对象集合的属性而不是对象本身来查找对JPA条件查询的结果进行排序的优雅方法。 E.g:

@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查询的一部分。

2 个答案:

答案 0 :(得分:0)

你不能吗

@Entity
class Parent {
  @OrderBy("timestamp DESC")
  protected Set<Child> children;
}

答案 1 :(得分:0)

我遇到了同样的情况。

请参阅JPA CriteriaQuery Order By Latest Child Property

对于您的具体情况,诀窍是不要在订单之前添加过滤器。 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 Property)中添加子查询,请同时添加过滤器。像这样:

criteriaQuery.where(subQueryCondition, filters));
filtersAdded = Boolean.TRUE;