具有聚合内部连接的 JPA 条件查询
JPA Criteria query with inner join of aggregation
我正在尝试编写一个 CriteriaQuery,它将查询每个城市的最新观察结果。城市由 city_code 字段定义,而最新记录由 observation_time 字段定义。
我可以很容易地用普通的方式写出来 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`
不幸的是,JPA 不支持 FROM
子句中的子查询。您需要编写本机查询或使用 FluentJPA.
之类的框架
当你打开效率低下时,这是可能的。
因此,首先让我们将查询转换为逻辑等效查询:
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();
}
我正在尝试编写一个 CriteriaQuery,它将查询每个城市的最新观察结果。城市由 city_code 字段定义,而最新记录由 observation_time 字段定义。
我可以很容易地用普通的方式写出来 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`
不幸的是,JPA 不支持 FROM
子句中的子查询。您需要编写本机查询或使用 FluentJPA.
当你打开效率低下时,这是可能的。 因此,首先让我们将查询转换为逻辑等效查询:
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();
}