如何使用 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 数据库中的结构:
任务:
- id
- 标题
- 描述
- project_id
项目:
- id
- 姓名
- 描述
主要问题:
我现在需要的是加入按“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();
希望对您有所帮助
花了无数个小时后,我得出了以下解决方案:
步骤:
- 以 Root 身份创建任务 table。
Root<Task> task = criteria.from(Task.class);
- 使用任务加入项目,并将 JoinType 设置为左联接。
Join<Task, Project> projectJoin = task.join(Task_.project, JoinType.LEFT);
- 分组依据为“任务”的“project_id”table。
criteria.groupBy(task.get(Task_.project));
- 使用了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"));
- 最后像这样返回了我想要的 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();
});
}
这是我的项目实体:(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 数据库中的结构:
任务:
- id
- 标题
- 描述
- project_id
项目:
- id
- 姓名
- 描述
主要问题:
我现在需要的是加入按“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();
希望对您有所帮助
花了无数个小时后,我得出了以下解决方案:
步骤:
- 以 Root 身份创建任务 table。
Root<Task> task = criteria.from(Task.class);
- 使用任务加入项目,并将 JoinType 设置为左联接。
Join<Task, Project> projectJoin = task.join(Task_.project, JoinType.LEFT);
- 分组依据为“任务”的“project_id”table。
criteria.groupBy(task.get(Task_.project));
- 使用了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"));
- 最后像这样返回了我想要的 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();
});
}