代码之家  ›  专栏  ›  技术社区  ›  Setsuna F. Seiei

使用Hibernate Criteria API返回每组的第一行

  •  5
  • Setsuna F. Seiei  · 技术社区  · 7 年前

    我刚开始使用Hibernate,我正在尝试编写一个条件查询,以返回给定日期员工的最新状态

    id  |   Status  | status_date
    1   |   Active  |   1/10/2017
    2   |   Active  |   1/10/2017
    ...
    1   |   Inactive|   5/10/2017
    ...
    1   |   Active  |   9/10/2017
    

    因此,我将向查询传递一个日期,并希望找到每个员工在该日期的最新状态 预期结果如下

    示例:对于2017年6月1日,这将是返回的数据

    id  |   Status  |   Date
    1   |   Inactive|   5/10/2017
    2   |   Active  |   1/10/2017
    

    我可以添加id为的group by,并按状态日期降序排列行。有没有办法只为每组选择最上面的一行?我试图在status\u 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")));
    
    1 回复  |  直到 7 年前
        1
  •  4
  •   Mạnh Quyết Nguyễn    6 年前

    由于要输出聚合,所以不要将聚合用作条件,因此不应将其放置在 having 条款您必须将聚合添加到选择列表中。

    首先,必须创建聚合结果类(通常与实体类不同):

    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();
    }
    

    结果是:

    enter image description here

    旁注

    根据你所写的,你试图使用 JPA Criteria Hibernate Criteria . 对于 休眠条件 解决方案,您可以尝试阅读 @default locale 建议