3.1 依存エンティティのマッピング

SQL では、JOIN を使用してクエリを作成できます。HQLでも同じことは可能でしょうか?簡単に言うと「はい」です。しかし、完全な答えはもっと興味深いものになるでしょう。

まず、SQL で JOIN を記述する場合、ほとんどの場合、あるテーブルが別のテーブルを参照することを意味します。たとえば、タスク テーブルには、employee テーブルの id 列を参照するemployee_id 列が含まれています。

この依存関係は、Hibernate のアノテーションを使用して説明できます。まず、テーブルのエンティティを作成しましょう。まず、employee テーブルについて説明します。

@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;
}

すべて問題ありませんが、1 つ提案があります。最後の例の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;

アノテーションは、多くのEmployeeTaskエンティティが 1 つのEmployeeエンティティを参照できること@ManyToOneを Hibernate に伝えます。

また、アノテーションは、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 での結合の使用

次に、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フィールドがあるため、このクエリは機能します。

状況その2。

期限を過ぎたタスクがある従業員のリストを返します。SQL でのクエリは次のようになります。

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

DISTINCT1 人のユーザーに多くのタスクを割り当てることができるため、これが使用されます。

次に、同じクエリを HQL で書いてみましょう。

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

このクエリの従業員は、 EmployeeTaskクラスのフィールドです。

状況その3。

割り当てられていないすべてのタスクをディレクターに割り当てます。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。ただし、これについては少し後で説明します。