保全の問題

今日は、Hibernate 機能を使用してクラス階層をデータベースに保存する、新しくて非常に興味深いスキームを紹介します。

クラス階層は、継承関係によって相互に関連付けられたクラスのセットです。

データベースに保存したい 3 つのクラスがあると想像してください。

class User {
  int id;
  String name;
  LocalDate birthday;
}
class Employee extends User {
 	String occupation;
 	int salary;
 	LocalDate join;
}
class Client extends User {
   String address;
}

クラスは相互に継承されます。そして最も興味深いのは、これらのクラスのオブジェクトをデータベースに保存するために Hibernate を使用したいということです。

ソリューションの種類

Hibernate には、クラス階層をデータベース内のテーブルに関連付ける方法が 4 つあります。

  • マップされたスーパークラス
  • 単一のテーブル
  • 結合されたテーブル
  • クラスごとのテーブル

各戦略は、データベース内に独自のテーブル構造を想定しています。場合によっては、非常に複雑な場合もあります。しかし、それらに対する HQL のクエリは非常に簡単です。まさに、Hibernate の利点が顕著に現れるケースです。

これらの用語がロシア語に翻訳されているのを聞いたことがないので、英語で発音することをお勧めします。

以下では、それぞれが何を意味するのかを分析していきます。

@MappedSuperClass

最も単純な解決策から始めましょう。データベースにはクラスごとに個別のテーブルがあります。たとえば、次のようなものがあります。

CREATE TABLE user {
  id INT,
  name VARCHAR,
  birthday DATE
}
CREATE TABLE employee {
  id INT,
  name VARCHAR,
  birthday DATE,
  occupation VARCHAR,
  salary INT,
  join DATE
}
CREATE TABLE client {
  id INT,
  name VARCHAR,
  birthday DATE,
  address VARCHAR
}

これらのテーブルのクラスが階層的に接続されていることは、あなただけが知っています。Hibernate にもこれを認識させたい場合は、@MappedSuperclassアノテーションを親クラスに追加する必要があります。これがないと、Hibernate は親クラスのフィールドとアノテーションを単に無視します。

このアノテーションを持つクラスは次のようになります。

@MappedSuperclass
class User {
  int id;
  String name;
  LocalDate birthday;
}
@Entity
class Employee extends User {
 	String occupation;
 	int salary;
 	LocalDate join;
}
@Entity
class Client extends User {
   String address;
}

これは、クラス階層とデータベースをリンクする最も原始的な方法です。このアプローチでは、実際にはクラス内の重複フィールドを回避できるだけです。

HQL でのデータベース クエリは、タイプが明示的に指定されたエンティティのみを返します。HQL でデータベース クエリを作成して、すべてのユーザー (ユーザー、従業員、クライアント) のリストを取得することはできません。