如何使用Hibernate(5.4)Criteria进行分组查询并连接两个表格?

huangapple go评论76阅读模式
英文:

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

}


期望的数据传输对象:(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
}

数据库中的表结构:

tasks:

  • id
  • title
  • description
  • project_id

projects:

  • id
  • name
  • description

主要问题:

现在我需要连接“projects”表和“tasks”表,按“project_id”列分组。并获得List作为输出。

我已经用HQL做过了,现在我必须学习如何在Hibernate Criteria中做到这一点。

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

(感谢您的阅读和对开源社区的支持)


<details>
<summary>英文:</summary>

**This is my Project Entity: ( 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 = &quot;project&quot;,
        cascade = CascadeType.REMOVE,
        orphanRemoval = true,
        fetch = FetchType.LAZY
)
private List&lt;Task&gt; tasks = new ArrayList&lt;&gt;();

public Project() {}

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

// getter setter here

}


**This is my Task Entity: ( Task.java )**
-------------------------------------

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

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

@Column(name = &quot;title&quot;)
private String title;

@Column(name = &quot;description&quot;)
private String description;

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

public Task() {}

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

// getter setter here

}


**Desired 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 structure in database:**
----------------------------

tasks:

 - id
 - title
 - description
 - project_id

projects:

 - id
 - name
 - description

**The main question:**
------------------

What I need now is to join the &quot;projects&quot; table and &quot;tasks&quot; table grouping by the &quot;project_id&quot; column. And obtain List&lt;ProjectWithSumOfTaskDto&gt; as output.

I have done it with HQL, Now I have to learn how to do it in hibernate criteria.

I&#39;m using hibernate version 5.4 (latest)

*(Thanks for reading and many love for open source community)*


</details>


# 答案1
**得分**: 3

以下是翻译好的部分:

**步骤:**

 1. 将Task表设为根表。
```java
Root<Task> task = criteria.from(Task.class);
  1. 将Project与Task进行连接,并将连接类型设置为左连接。
Join<Task, Project> projectJoin = task.join(Task_.project, JoinType.LEFT);
  1. 以"tasks"表的"project_id"为标准进行分组。
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();
    });
}
英文:

After spending countless hours, I came by this solution below:

Steps:

  1. Made Task table as Root.
Root&lt;Task&gt; task = criteria.from(Task.class);
  1. Joined Project with Task, and made the JoinType as Left join.
Join&lt;Task, Project&gt; projectJoin = task.join(Task_.project, JoinType.LEFT);
  1. Grouped by with "project_id" of "tasks" table.
criteria.groupBy(task.get(Task_.project));
  1. Used multi-select and selected the task.project_id, project.name, and the count of task rows after group by.
criteria.multiselect(projectJoin.get(Project_.ID).alias(&quot;projectId&quot;),
                     projectJoin.get(Project_.NAME).alias(&quot;name&quot;),
                     builder.count(task).alias(&quot;totalTasks&quot;));
  1. And finally returned the list of my desired DTO like this:
return session.createQuery(criteria).getResultList();

Together, the code will look like this:

public List&lt;ProjectWithSumOfTaskDto&gt; projectsWithTaskCount() {
    return criteriaBuilderContext((session, builder) -&gt; {

        CriteriaQuery&lt;ProjectWithSumOfTaskDto&gt; criteria = builder.createQuery(
                ProjectWithSumOfTaskDto.class
        );

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

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

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

答案2

得分: 1

我没有使用您的DTO,我使用的是您的基类,而且我也没有运行它,
解决方案是:

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

希望这对您有帮助。

英文:

i am not using your dto what i am using is your base class and i also dont run it,
the solution is :

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

i hope this is helpful

huangapple
  • 本文由 发表于 2020年10月6日 04:56:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/64216085.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定