Запрос JPA Criteria с внутренним объединением агрегации - PullRequest
0 голосов
/ 10 октября 2019

Я пытаюсь написать CriteriaQuery, который будет запрашивать последние наблюдения для каждого города. Город определяется полем city_code, а последняя запись - полем наблюдения.

Я могу легко написать его простым SQL, но не могу понять, как это сделать с помощью критериев jpa api.

select distinct m.* from 
 (select city_code cc, max(observation_time) mo
 from observations group by city_code) mx, observations m 
 where m.city_code = mx.cc and m.observation_time = mx.mo`

Ответы [ 2 ]

0 голосов
/ 15 октября 2019

Это возможно, когда Вы открыты для потери эффективности. Итак, сначала давайте преобразуем наш запрос в логически эквивалентный:

select distinct m.* from observations m where 
m.observation_time = (select max(inn. observation_time) from observations inn 
                      where inn.city_code = m.city_code);

, а затем переведем его в JPA CriteriaQuery:

public List<Observation> maxForEveryWithSubquery() {
    CriteriaBuilder builder = entityManager.getCriteriaBuilder();
    CriteriaQuery<Observation> query = builder.createQuery(Observation.class);
    Root<Observation> observation = query.from(Observation.class);
    query.select(observation);

    Subquery<LocalDateTime> subQuery = query.subquery(LocalDateTime.class);
    Root<Observation> observationInner = subQuery.from(Observation.class);
    subQuery.where(
            builder.equal(
                    observation.get(Observation_.cityCode),
                    observationInner.get(Observation_.cityCode)
            )
    );
    Subquery<LocalDateTime> subSelect = subQuery.select(builder.greatest(observationInner.get(Observation_.observationTime)));
    query.where(
            builder.equal(subSelect.getSelection(), observation.get(Observation_.observationTime))
    );
    TypedQuery<Observation> typedQuery = entityManager.createQuery(query);
    return typedQuery.getResultList();
}
0 голосов
/ 13 октября 2019

К сожалению, JPA не поддерживает подзапросы в предложении FROM. Вам нужно написать собственный запрос или использовать фреймворк, такой как FluentJPA .

...