简体   繁体   English

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

[英]Criteria API Ordering by nested aggregated property

How do I implement ordering objects by aggregated nested property?如何通过聚合的嵌套属性实现排序对象? I have Photographer entity which one has a lot of PhotographerPrice entities (One to Many) with BigDecimal property called pricePerHour.我有摄影师实体,其中一个有很多摄影师价格实体(一对多),BigDecimal 属性称为 pricePerHour。 When I retrieving photographers I want to sort them by the minimal price of whole prices they have.当我检索摄影师时,我想按他们拥有的整体价格的最低价格对他们进行排序。

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

I tried to make a subquery to PhotographerPrice and than sort in root我试图对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));

But, as I realized, it's not allowed to use a subquery in order by clause.但是,正如我意识到的那样,不允许在 order by 子句中使用子查询。

So, how do I can implement something like this using Criteria API:那么,我如何使用 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
    );

When I tried to implement it with Join approach I've got duplicates in my result list.当我尝试使用 Join 方法来实现它时,我的结果列表中有重复项。

Is it possible to implement it using Criteria API?是否可以使用标准 API 来实现它? Maybe there is another tool to make filtering for entities from DB more convenient?也许还有另一种工具可以更方便地过滤来自 DB 的实体? I have a lot of different parameters for filtering and sorting which related to nested properties, sometimes even related to nested in a nested property.我有很多不同的参数用于过滤和排序,这些参数与嵌套属性相关,有时甚至与嵌套在嵌套属性中相关。

The only way I found to solve it:我发现解决它的唯一方法:

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));

But I don't sure about group by.但我不确定分组依据。 Is it possible some troubleshooting appear later?以后可能会出现一些故障排除吗?

The approach I found that works in my case我发现在我的情况下有效的方法

Do left join to PhotographerPrice with Min aggregate function after that make an order based by result of this aggregate:使用 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