Фильтрация по агрегированным полям в запросе JPA critera - PullRequest
0 голосов
/ 19 сентября 2019

У меня проблема с написанием Specification, который будет сортировать по совокупности.Допустим, у меня есть 2 сущности:

@Entity
public class Property {

    @Id
    @GeneratedValue
    private Long id;

    @OneToMany
    @Cascade(org.hibernate.annotations.CascadeType.ALL)
    private List<Feedback> ratings;
}

и

@Entity
public class Feedback {

    @Id
    @GeneratedValue
    private Long id;

    @Column(nullable = false)
    private Integer rating;
}

Я пытаюсь добиться того, чтобы получить все Properties со средним рейтингом выше заданного порога.Итак, вот что я придумала, используя всемогущий Google:

private static Specification<Property> ratingsSpec(Double minRating) {
    return (root, query, criteriaBuilder) -> {
        ListJoin<Property, Feedback> feedbackJoin = root.join(Property_.ratings);
        return criteriaBuilder.greaterThanOrEqualTo(criteriaBuilder.avg(feedbackJoin.get(Feedback_.rating)), minRating);
    };
}

Но при попытке запуска я получаю следующую ошибку:

Invalid use of aggregate function "AVG(CAST(FEEDBACK2_.RATING AS DOUBLE))"; 
SQL statement:
select property0_.id as id1_1_, property0_.additional_info as addition2_1_, property0_.address_line1 as address_3_1_, property0_.address_line2 as address_4_1_, property0_.city as city5_1_, property0_.postcode as postcode6_1_, property0_.area_sqm as area_sqm7_1_, property0_.rooms as rooms8_1_, property0_.type as type9_1_, property0_.version as version10_1_ from property property0_ inner join property_ratings ratings1_ on property0_.id=ratings1_.property_id inner join feedback feedback2_ on ratings1_.ratings_id=feedback2_.id where 1=1 and avg(cast(feedback2_.rating as double))>=3.9 [90054-199]

Я скопировал ошибкуточно, чтобы не пропустить ничего важного, очевидно, там больше полей, чем я упоминал выше.

Теперь я вижу проблему с запросом, условие обязательно должно быть в предложении having, а не where, и я пропускаю предложение group by.Но как мне этого добиться?Будем благодарны за любую помощь.

Бонусный вопрос: Как отсортировать по одному значению?;)

1 Ответ

0 голосов
/ 19 сентября 2019

На самом деле удалось сделать это с помощью запроса.Я не уверен, что это лучшее решение, поэтому, если у кого-то есть какой-то вклад, я весь слух.Вот рабочее решение:

private static Specification<Property> ratingsSpec(Double minRating) {
        return (root, query, criteriaBuilder) -> {
            ListJoin<Property, Feedback> feedbackJoin = root.join(Property_.ratings);
            Expression<Double> avg = criteriaBuilder.avg(feedbackJoin.get(Feedback_.rating));
            return query.groupBy(root).having(criteriaBuilder.greaterThanOrEqualTo(avg, minRating)).getRestriction();
        };
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...