使用 Hibernate Criteria API 到 return 每组的第一行
Use Hibernate Criteria API to return first row of each group
我是 Hibernate 的新手,我正在尝试编写条件查询以获取 return 员工在给定日期的最新状态
id | Status | status_date
1 | Active | 1/10/2017
2 | Active | 1/10/2017
...
1 | Inactive| 5/10/2017
...
1 | Active | 9/10/2017
所以我将向查询传递一个日期,并希望找到该日期每个员工的最新状态
预期的结果将是这样的
示例:对于日期 6/1/2017,这将是 returned 数据
id | Status | Date
1 | Inactive| 5/10/2017
2 | Active | 1/10/2017
我能够添加带有 id 的分组依据,并按状态日期对行进行降序排序。有什么办法可以 select 每个组的第一行吗?我尝试在 status_date 上使用 max 函数,但这不起作用。
CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();
CriteriaQuery<Employee> cq = builder.createQuery(Employee);
Root<Employee> root = cq.from(Employee.class);
cq.select(root);
cq.groupBy(root.get("id"));
cq.orderBy(builder.desc(root.get("status_date")));
cq.having(builder.max(root.get("status_date")));
既然要输出聚合,就不要把聚合作为条件,所以不要放在having
子句中。您必须改为将聚合添加到选择列表。
首先你必须创建聚合结果class(通常与你的实体不同class):
public static class StatusEntityResult {
private String userId;
private String status;
private Date statusDate;
// getter, setter, constructor with all parameters here
}
然后使用它作为结果创建一个查询:
public List<StatusEntityResult> queryStatus() throws ParseException {
// Date condition
Date targetDate = new SimpleDateFormat("yyyy-MM-dd").parse("2017-10-06");
CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();
// Use StatusEntityResult as result
CriteriaQuery<StatusEntityResult> cq = builder.createQuery(StatusEntityResult.class);
Root<Employee> root = cq.from(Employee.class);
// Select `id`, `status` and `max(status_date)`
cq.multiselect(root.get("id"), root.get("status"), builder.max(root.get("statusDate")))
.where(builder.lessThanOrEqualTo(root.get("statusDate"), targetDate))
.groupBy(root.get("id"))
.orderBy(builder.desc(root.get("statusDate")));
return this.entityManager.createQuery(cq).getResultList();
}
结果是:
旁注
根据您所写的内容,您试图使用 JPA Criteria
,而不是 Hibernate Criteria
。 Hibernate Criteria
解决方案,可以尝试阅读@default locale
建议
我是 Hibernate 的新手,我正在尝试编写条件查询以获取 return 员工在给定日期的最新状态
id | Status | status_date
1 | Active | 1/10/2017
2 | Active | 1/10/2017
...
1 | Inactive| 5/10/2017
...
1 | Active | 9/10/2017
所以我将向查询传递一个日期,并希望找到该日期每个员工的最新状态 预期的结果将是这样的
示例:对于日期 6/1/2017,这将是 returned 数据
id | Status | Date
1 | Inactive| 5/10/2017
2 | Active | 1/10/2017
我能够添加带有 id 的分组依据,并按状态日期对行进行降序排序。有什么办法可以 select 每个组的第一行吗?我尝试在 status_date 上使用 max 函数,但这不起作用。
CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();
CriteriaQuery<Employee> cq = builder.createQuery(Employee);
Root<Employee> root = cq.from(Employee.class);
cq.select(root);
cq.groupBy(root.get("id"));
cq.orderBy(builder.desc(root.get("status_date")));
cq.having(builder.max(root.get("status_date")));
既然要输出聚合,就不要把聚合作为条件,所以不要放在having
子句中。您必须改为将聚合添加到选择列表。
首先你必须创建聚合结果class(通常与你的实体不同class):
public static class StatusEntityResult {
private String userId;
private String status;
private Date statusDate;
// getter, setter, constructor with all parameters here
}
然后使用它作为结果创建一个查询:
public List<StatusEntityResult> queryStatus() throws ParseException {
// Date condition
Date targetDate = new SimpleDateFormat("yyyy-MM-dd").parse("2017-10-06");
CriteriaBuilder builder = this.entityManager.getCriteriaBuilder();
// Use StatusEntityResult as result
CriteriaQuery<StatusEntityResult> cq = builder.createQuery(StatusEntityResult.class);
Root<Employee> root = cq.from(Employee.class);
// Select `id`, `status` and `max(status_date)`
cq.multiselect(root.get("id"), root.get("status"), builder.max(root.get("statusDate")))
.where(builder.lessThanOrEqualTo(root.get("statusDate"), targetDate))
.groupBy(root.get("id"))
.orderBy(builder.desc(root.get("statusDate")));
return this.entityManager.createQuery(cq).getResultList();
}
结果是:
旁注
根据您所写的内容,您试图使用 JPA Criteria
,而不是 Hibernate Criteria
。 Hibernate Criteria
解决方案,可以尝试阅读@default locale
建议