如何使用 Hibernate (5.4) Criteria 通过组查询连接两个表?

How to join two tables with a group query using Hibernate (5.4) Criteria?

这是我的项目实体:(Project.java)

@Entity
@Table(name = "project")
public class Project implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @Column
    private String name;

    @Column
    private String description;

    @OneToMany(
            mappedBy = "project",
            cascade = CascadeType.REMOVE,
            orphanRemoval = true,
            fetch = FetchType.LAZY
    )
    private List<Task> tasks = new ArrayList<>();

    public Project() {}

    public Project(String name, String description) {
        this.name = name;
        this.description = description;
    }

    // getter setter here
}

这是我的任务实体:(Task.java)

@Entity
@Table(name = "task")
public class Task implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @Column(name = "title")
    private String title;

    @Column(name = "description")
    private String description;

    @ManyToOne
    @JoinColumn(name = "project_id", referencedColumnName="id")
    private Project project;

    public Task() {}

    public Task(String title, String description) {
        this.title = title;
        this.description = description;
    }

    // getter setter here

}

所需的 DTO:(ProjectWithSumOfTaskDto.java)

public class ProjectWithSumOfTaskDto {

    private int projectId;
    private String name;
    private long totalTasks;

    public ProjectWithSumOfTaskDto(int id, String name, long totalTasks) {
        this.projectId = id;
        this.name = name;
        this.totalTasks = totalTasks;
    }

    // getter setter here
}

Table 数据库中的结构:

任务:

项目:

主要问题:

我现在需要的是加入按“project_id”列分组的“项目”table 和“任务”table。并获取 List 作为输出。

我已经用 HQL 做到了,现在我必须学习如何在休眠条件下做到这一点。

我正在使用休眠版本 5.4(最新)

(感谢阅读和对开源社区的热爱)

我没有使用你的 dto 我使用的是你的基础 class 而且我也不 运行 它, 解决方案是:

Criteria cr = session.createCriteria(Project.class, "p");
cr.createAlias("p.tasks", "t", Criteria.INNER_JOIN);
cr.add(Restrictions.eq("p.id",id);
return cr.list();

希望对您有所帮助

花了无数个小时后,我得出了以下解决方案:

步骤:

  1. 以 Root 身份创建任务 table。
Root<Task> task = criteria.from(Task.class);
  1. 使用任务加入项目,并将 JoinType 设置为左​​联接。
Join<Task, Project> projectJoin = task.join(Task_.project, JoinType.LEFT);
  1. 分组依据为“任务”的“project_id”table。
criteria.groupBy(task.get(Task_.project));
  1. 使用了multi-select并选择了task.project_id、project.name和分组依据后的任务行数。
criteria.multiselect(projectJoin.get(Project_.ID).alias("projectId"),
                     projectJoin.get(Project_.NAME).alias("name"),
                     builder.count(task).alias("totalTasks"));
  1. 最后像这样返回了我想要的 DTO 列表:
return session.createQuery(criteria).getResultList();

一起,代码将如下所示:

public List<ProjectWithSumOfTaskDto> projectsWithTaskCount() {
    return criteriaBuilderContext((session, builder) -> {

        CriteriaQuery<ProjectWithSumOfTaskDto> criteria = builder.createQuery(
                ProjectWithSumOfTaskDto.class
        );

        Root<Task> task = criteria.from(Task.class);
        Join<Task, Project> projectJoin = task.join(Task_.project, JoinType.LEFT);
        
        criteria.groupBy(task.get(Task_.project));

        criteria.multiselect(
            projectJoin.get(Project_.ID).alias("projectId"),
            projectJoin.get(Project_.NAME).alias("name"),
            builder.count(task).alias("totalTasks")
        );

        return session.createQuery(criteria).getResultList();
    });
}