3.1 映射依赖实体

在 SQL 中,您可以使用 JOIN 编写查询。可以在 HQL 中做同样的事情吗?简短的回答是肯定的。但完整的答案会更有趣。

首先,当我们在 SQL 中编写 JOIN 时,通常意味着一个表引用另一个表。例如,task 表包含一个 employee_id 列,该列引用 employee 表的 id 列。

这种依赖性可以在 Hibernate 中使用注解来描述。首先,让我们为表创建实体。首先,让我们描述一下员工表:

@Entity
@Table(name="employee")
class Employee {
   @Column(name="id")
   public Integer id;

   @Column(name="name")
   public String name;

   @Column(name="salary")
   public Integer salary;

   @Column(name="join_date")
   public Date joinDate;
}

任务表的EmployeeTask类:

@Entity
@Table(name="task")
class EmployeeTask {
   @Column(name="id")
   public Integer id;

   @Column(name="name")
   public String name;

   @Column(name="employee_id")
   public Integer employeeId;

   @Column(name="deadline")
   public Date deadline;
}

一切都很好,但有一个建议。我们来看最后一个例子中的employeeId字段:

@Column(name="employee_id")
public Integer employeeId;

你注意到什么奇怪的事了吗?如果没有,那么这意味着你已经形成了SQL语言的思维方式。

问题是,在 Java 语言中,我们通常对这种依赖关系的描述略有不同:

public Employee employee;

我们不需要指定id,我们通常只指定一个变量来保存对Employee对象的引用。如果没有这样的对象,则存储null 。

而 Hibernate 允许我们使用注解来描述这样的情况:

@ManyToOne
@JoinColumn(name="employee_id", nullable=true)
public Employee employee;

注释@ManyToOne告诉 Hibernate 许多EmployeeTask实体可以引用一个Employee实体。

并且注释指定了从中获取id@JoinColumn的列的名称。所有其他必要的信息将从 Employee 类的注释中获取。

最终结果将如下所示:

@Entity
@Table(name="task")
class EmployeeTask
{
   @Column(name="id")
   public Integer id;

   @Column(name="name")
   public String name;

   @ManyToOne
   @JoinColumn(name="employee_id", nullable=true)
   public Employee employee;

   @Column(name="deadline")
   public Date deadline;
}

3.2 在HQL中使用join

现在让我们看看如何在 HQL 中编写对相关实体的查询。

第一种情况。

我们有一个员工(Employee),我们想得到他的任务列表。下面是该查询在 SQL 中的样子:

SELECT task.* FROM task JOIN employee ON task.employee_id = employee.id
WHERE employee.name = "Ivan Ivanovich";

现在让我们用 HQL 编写相同的查询:

from EmployeeTask where employee.name = "Ivan Ivanovich"

EmployeeTask类有一个employee字段,还有一个name字段,所以这个查询会起作用。

情况二。

返回有逾期任务的员工列表。下面是该查询在 SQL 中的样子:

SELECT DISTINCT employee.*
FROM task JOIN employee ON task.employee_id = employee.id
WHERE task.deadline < CURDATE();

DISTINCT之所以使用,是因为可以将许多任务分配给一个用户。

现在让我们用 HQL 编写相同的查询:

select distinct employee from EmployeeTask where deadline < CURDATE();

此查询中的员工是EmployeeTask类的一个字段

情况三。

将所有未分配的任务分配给主管。SQL 查询将如下所示:

UPDATE task SET employee_id = 4 WHERE employee_id IS NULL

现在让我们用 HQL 编写相同的查询:

update EmployeeTask set employee = :user where employee is null

最后一个查询是最难的。我们需要传递 ID,director,但是 EmployeeTask 类不包含可以写入 id 的字段,而是包含一个 Employee 字段,您需要在该字段中分配对 Employee 类型对象的引用。

在 Hibernate 中,这个问题是在传递给 Query 对象的查询参数的帮助下解决的。而在 HQL 本身中,此类参数是通过冒号编写的::user。但是我们稍后会讨论这个。