将SQL转换为CriteriaBuilder语句

时间:2019-02-09 19:40:21

标签: java postgresql jpa

您能帮助我将此SQL语句转换为CriteriaBuilder语句吗?我遇到的问题是INNER JOIN语句。

SELECT th.id, th.date, th.exercise_id
FROM traininghistory th
INNER JOIN (
  SELECT exercise_id, MAX(date) as maxdate
  FROM traininghistory
  group by exercise_id
  ) AS tm on tm.exercise_id = th.exercise_id AND th.date = tm.maxdate
WHERE th.accountid = :accountId

@Entity
public class TrainingHistory {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @NotNull
    public Long id;

    public Long accountId;

    @ManyToOne
    public Exercise exercise;

    public Date dateDone = new Date();

    public WellBeing wellBeing;

    public int weight;

    public int repetitions;

    public int duration;
}

1 个答案:

答案 0 :(得分:1)

通过重新构造不带INNER JOIN的查询来找到解决方案。以下SQL查询可达到与问题中的SQL查询相同的结果,但对我而言可以转换为Criteria API。

FROM traininghistory th
WHERE th.datedone in (
SELECT MAX(tm.datedone)
  FROM traininghistory tm
  GROUP BY tm.exercise_id
)
AND th.accountid = :userId

因此,以此为基础,使用Criteria API的语句如下:

// define query
CriteriaBuilder cb = this.entityManager.getCriteriaBuilder();
CriteriaQuery<TrainingHistory> query = cb.createQuery(TrainingHistory.class);
Root<TrainingHistory> root = query.from(TrainingHistory.class);
query.select(root);

// define subquery
Subquery<Integer> subquery = query.subquery(Integer.class);
Root<TrainingHistory> rootSubquery = subquery.from(TrainingHistory.class);
Expression<Integer> max = cb.max(rootSubquery.get(TrainingHistory_.DATE_DONE));
   subquery.select(max);
   subquery.groupBy(rootSubquery.get(TrainingHistory_.exercise));

// compose whole query
query.where(
   cb.and(
      cb.in(root.get(TrainingHistory_.DATE_DONE)).value(subquery),
      cb.equal(root.get(TrainingHistory_.ACCOUNT_ID), userId)
  )
);

return this.entityManager.createQuery(query).getResultList();