2.1 テーブルレベルでのリンク

Hibernate がコレクションを補助テーブルにどのように保存するかを見てきました。次に、実際のエンティティ クラスを格納する本格的なテーブル間の関係を整理する方法を考えてみましょう。

Hibernate のエンティティ クラス間の関係には 4 つのタイプがあります。

  • 11
  • 1

そして、最も単純なオプションであるmany -to- oneで分析を開始します。

SQL のテーブル間のこのような関係はすでに見たことがあります。通常は次のようになります。

ID 名前 職業 給料 参加日
1 イワノフ・イワン プログラマー 100000 25 2012-06-30
2 ペトロフ・ペトル プログラマー 80000 23 2013-08-12
3 イワノフ・セルゲイ テスター 40000 30 2014-01-01
4 ラビノビッチ・モイシャ 監督 200000 35 2015-05-12
5 キリエンコ・アナスタシア 事務長 40000 25 2015-10-10
6 バスカ 1000 3 2018-11-11

従業員テーブル:

このテーブルには次の列があります。

  • ID INT
  • 名前VARCHAR
  • 職業VARCHAR
  • 給与INT
  • 年齢INT
  • 参加日DATE

従業員のタスクを含むタスク テーブルは次のようになります。

ID 従業員ID 名前 締め切り
1 1 フロントエンドのバグを修正 2022-06-01
2 2 バックエンドのバグを修正 2022-06-15
3 5 コーヒーを買う 2022-07-01
4 5 コーヒーを買う 2022-08-01
5 5 コーヒーを買う 2022-09-01
6 (ヌル) オフィスを掃除する (ヌル)
7 4 人生を楽しむ (ヌル)
8 6 人生を楽しむ (ヌル)

このテーブルには 4 つの列しかありません。

  • id – 一意のタスク番号 (およびテーブル内の行)。
  • employee_id – タスクが割り当てられている従業員テーブルの従業員 ID。
  • name - タスクの名前と説明。
  • 期限- タスクを完了しなければならない時間。

タスク テーブルの多くの行が従業員テーブルの 1 つのエントリを参照できることがわかります。このようなテーブルレベルの関係は、多対1 と呼ばれます。

2.2 Javaクラスレベルとの関係

テーブル レベルでの通信に加えて、Hibernate ではエンティティ クラス レベルでの通信を整理することもできます。これはアノテーションを使用して行われます@ManyToOne

まず、EmployeeEmployeeTaskという 2 つのクラスを作成しましょう。


@Entity
@Table(name="employee")
class Employee {
   @Column(name="id")
   public Integer id;
 
   @Column(name="name")
   public String name;
 
   @Column(name="occupation")
   public String occupation;
 
   @Column(name="salary")
   public Integer salary;
 
   @Column(name="join_date")
   public Date join;
}

そして、従業員のジョブを保存するための 2 番目のクラス:


@Entity
@Table(name="task")
class EmployeeTask {
   @Column(name="id")
   public Integer id;
 
   @Column(name="name")
   public String description;
 
  @Column(name="employee_id")
   public Integer employeeId;
 
   @Column(name="deadline")
   public Date deadline;
}

これらのクラスには問題はありませんが、それらの間には、EmployeeTask クラスのemployeeId フィールドが Employee クラスの id フィールドを参照しているという事実を反映するような関係はありません。それを直す時が来た

2.3 @ManyToOne アノテーション。

まず、Java では、ID ではなくオブジェクト (およびオブジェクト参照) を操作することに慣れています。そこでまず、EmployeeTask クラスのemployeeId フィールドの代わりに、Employee 型のオブジェクトを指すようにします。新しいクラスは次のようになります。


@Entity
@Table(name="task")
class EmployeeTask {
   @Column(name="id")
   public Integer id;
 
   @Column(name="name")
   public String description;
 
   @ManyToOne
   @JoinColumn(name = "employee_id")
   public Employee employee;
 
   @Column(name="deadline")
   public Date deadline;
}

注釈 の助けを借りて@ManyToOne、多くの EmployeeTask オブジェクトが Employee 型の 1 つのオブジェクトを参照できることを示しました。また、注釈 @JoinColumnを使用して、テーブルのどの列に Employee オブジェクトの ID が格納されているかを示しました。

2.4 リクエストの例

ここで、Hibernate がそのような関連クラスとどのように連携できるかの例をいくつか示しましょう。

シナリオ 1

特定のユーザーに割り当てられているすべてのタスクを検索するクエリを作成してみましょう。このクエリは HQL でどのように表示されるかを次に示します。

from EmployeeTask where employee.name = "Ivan Ivanovich"

ドットを介して依存クラスのフィールドを簡単に参照できます。とても快適です。ただし、このクエリを Java コードの形式で記述してみましょう。


String hql = "from EmployeeTask where employee.name = :username";
Query<EmployeeTask> query = session.createQuery( hql, EmployeeTask.class);
query.setParameter("username", "Ivan Ivanovich");
List<EmployeeTask> resultLIst = query.list();

シナリオ 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 を渡す必要がありますが、EmployeeTask クラスには ID を書き込むフィールドが含まれておらず、代わりに、Employee 型のオブジェクトへの参照を割り当てる必要がある Employee フィールドが含まれています。


Employee director = session.get(Employee.class, 4);
 
String hql = "update EmployeeTask set employee = :user where employee is null";
Query<EmployeeTask> query = session.createQuery(hql, EmployeeTask.class);
query.setParameter("user", director);
query.executeUpdate();