繁体   English   中英

标准 API 按嵌套聚合属性排序

[英]Criteria API Ordering by nested aggregated property

如何通过聚合的嵌套属性实现排序对象? 我有摄影师实体,其中一个有很多摄影师价格实体(一对多),BigDecimal 属性称为 pricePerHour。 当我检索摄影师时,我想按他们拥有的整体价格的最低价格对他们进行排序。

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Photographer> cq = cb.createQuery(Photographer.class);
Root<Photographer> root = cq.from(Photographer.class);
List<Predicate> predicates = new ArrayList<>(); // I have a lot of predicates which set if data was present by client

我试图对PhotographerPrice进行子查询,而不是在root中排序

Subquery<BigDecimal> subquery = cq.subquery(BigDecimal.class);
Root<PhotographerPrice> from = subquery.from(PhotographerPrice.class);
Predicate and = cb.and(
        cb.equal(root.get(Photographer_.id), from.get(PhotographerPrice_.photographer).get(Photographer_.id)),
        cb.isNotNull(from.get(PhotographerPrice_.pricePerHour))
);
subquery.correlate(root);
subquery.where(and);
subquery.select(cb.min(from.get(PhotographerPrice_.pricePerHour)));
subquery.groupBy(from.get(PhotographerPrice_.photographer).get(Photographer_.id));

...

cq.orderBy(cb.asc(subquery));

但是,正如我意识到的那样,不允许在 order by 子句中使用子查询。

那么,我如何使用 Criteria API 来实现这样的事情:

select *
  from photographer p
  order by (
    select min(price_per_hour) minPrice
      from photographer_price pp
      where p.id = pp.photographer_id
        and pp.photo_per_hour is not null
      group by photographer_id
    );

当我尝试使用 Join 方法来实现它时,我的结果列表中有重复项。

是否可以使用标准 API 来实现它? 也许还有另一种工具可以更方便地过滤来自 DB 的实体? 我有很多不同的参数用于过滤和排序,这些参数与嵌套属性相关,有时甚至与嵌套在嵌套属性中相关。

我发现解决它的唯一方法:

ListJoin<Photographer, PhotographerPrice> join = root.join(Photographer_.photographerPrices);
Expression<BigDecimal> min = cb.min(join.get(PhotographerPrice_.pricePerHour));
cq.orderBy(cb.desc(min));
cq.groupBy(root.get(Photographer_.id));

但我不确定分组依据。 以后可能会出现一些故障排除吗?

我发现在我的情况下有效的方法

使用 Min 聚合 function 左连接到PhotographerPrice,然后根据此聚合的结果下订单:

ListJoin<Photographer, PhotographerPrice> photographerPriceJoin = root.join(Photographer_.photographerPrices);
Expression<BigDecimal> min = cb.min(photographerPriceJoin.get(PhotographerPrice_.pricePerHour));
if (photographerCatalogFilter.getDirection().isDescending()) {
    orderList.add(cb.desc(min));
} else {
    orderList.add(cb.asc(min));
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM