1. 序章

このチュートリアルでは、JPAとHibernateを使用した一意の制約の定義について説明します。

最初に、固有の制約と、それらが主キー制約とどのように異なるかを調べます。

次に、JPAの重要な注釈@を見ていきます。 列(一意= true) @UniqueConstraint。 それらを実装して、単一の列と複数の列に一意の制約を定義します。

最後に、参照されるテーブル列に一意の制約を定義する方法を学習します。

2. 固有の制約

簡単な要約から始めましょう。 一意キーは、データベーステーブル内のレコードを一意に識別するテーブルの単一または複数の列のセットです。

一意キー制約と主キー制約の両方が、列または列のセットの一意性を保証します。

2.1. 主キーの制約とどのように違いますか?

一意の制約により、列または列の組み合わせのデータが各行で一意になります。 たとえば、テーブルの主キーは、暗黙の一意性制約として機能します。 したがって、主キー制約には自動的に一意の制約があります。

さらに、テーブルごとに1つの主キー制約のみを持つことができます。 ただし、テーブルごとに複数の一意の制約が存在する可能性があります。 簡単に言えば、主キーマッピングに伴う制約に加えて、一意の制約が適用されます。

定義した一意の制約は、テーブルの作成時に適切なデータベース制約を生成するために使用されます。また、実行時に挿入更新、または削除を注文するために使用される場合もあります。ステートメント。

2.2. 単一列および複数列の制約とは何ですか?

一意の制約は、列制約またはテーブル制約のいずれかです。 テーブルレベルでは、複数の列にまたがる一意の制約を定義できます。

JPAを使用すると、@ Column(unique = true)と@UniqueConstraintを使用して、コードに一意の制約を定義できます。 これらの注釈はスキーマ生成プロセスによって解釈され、制約が自動的に作成されます。

何よりもまず、列レベルの制約は単一の列に適用され、テーブルレベルの制約はテーブル全体に適用されることを強調する必要があります。

これについては、次のセクションで詳しく説明します。

3. エンティティを設定する

JPAのentityは、データベースに格納されているテーブルを表します。 エンティティのすべてのインスタンスは、テーブル内の行を表します。

ドメインエンティティを作成し、それをデータベーステーブルにマッピングすることから始めましょう。 この例では、 Personentityを作成します。

@Entity
@Table
public class Person implements Serializable {
    @Id
    @GeneratedValue
    private Long id;  
    private String name;
    private String password;
    private String email;
    private Long personNumber;
    private Boolean isActive;
    private String securityNumber;
    private String departmentCode;
    @JoinColumn(name = "addressId", referencedColumnName = "id")
    private Address address;
   //getters and setters
 }

address フィールドは、Addressエンティティからの参照フィールドです。

@Entity
@Table
public class Address implements Serializable {
    @Id
    @GeneratedValue
    private Long id;
    private String streetAddress;
    //getters and setters
}

このチュートリアル全体を通して、このPersonエンティティを使用して例を示します。

4. 列の制約

モデルの準備ができたら、最初の一意の制約を実装できます。

個人の情報を保持するPersonエンティティについて考えてみましょう。 id列の主キーがあります。 このエンティティは、重複する値を含まない PersonNumber、も保持します。 さらに、テーブルにすでに主キーがあるため、主キーを定義できません。

この場合、列の一意の制約を使用して、PersonNumberフィールドに重複する値が入力されないようにすることができます。 JPAでは、unique属性を持つ@Columnアノテーションを使用してこれを実現できます。

次のセクションでは、 @Column アノテーションを見て、それを実装する方法を学びます。

4.1. @Column(unique = true)

注釈タイプColumnは、永続プロパティまたはフィールドのマップされた列を指定するために使用されます。

定義を見てみましょう:

@Target(value={METHOD,FIELD})
@Retention(value=RUNTIME)
public @interface Column {
    boolean unique;
   //other elements
 }

unique 属性は、列が一意のキーであるかどうかを指定します。 これは、 UniqueConstraint アノテーションのショートカットであり、一意キー制約が単一の列のみに対応する場合に役立ちます。

次のセクションでそれを定義する方法を見ていきます。

4.2. 列制約の定義

一意の制約が1つのフィールドのみに基づいている場合は常に、その列で @Column(unique = true)を使用できます。

personNumberフィールドに一意の制約を定義しましょう。

@Column(unique=true)
private Long personNumber;

スキーマ作成プロセスを実行すると、ログから検証できます。

[main] DEBUG org.hibernate.SQL -
    alter table Person add constraint UK_d44q5lfa9xx370jv2k7tsgsqt unique (personNumber)

同様に、 Person を制限して一意の電子メールに登録する場合は、emailフィールドに一意の制約を追加できます。

@Column(unique=true)
private String email;

スキーマ作成プロセスを実行して、制約を確認しましょう。

[main] DEBUG org.hibernate.SQL -
    alter table Person add constraint UK_585qcyc8qh7bg1fwgm1pj4fus unique (email)

これは、単一の列に一意の制約を設定する場合に便利ですが、列の組み合わせである複合キーに一意の制約を追加したい場合があります。 複合一意キーを定義するために、テーブル制約を使用できます。 これについては、次のセクションで説明します。

5. テーブルの制約

複合一意キーは、列の組み合わせで構成される一意キーです。 複合一意キーを定義するために、列の代わりにテーブルに制約を追加できます。 JPAは、@UniqueConstraintアノテーションを使用してこれを実現するのに役立ちます。

5.1. @UniqueConstraintアノテーション

注釈タイプUniqueConstraintは、テーブル用に生成されたDDL(データ定義言語)に一意の制約を含めることを指定します。

定義を見てみましょう:

@Target(value={})
@Retention(value=RUNTIME)
public @interface UniqueConstraint {
    String name() default "";
    String[] columnNames();
}

ご覧のとおり、タイプStringおよびString []のnameおよびcolumnNamesは、それぞれ、UniqueConstraintアノテーションに指定できるアノテーション要素です。

次のセクションでは、例を見て、各パラメーターを詳しく見ていきます。

5.2. 一意の制約の定義

Personエンティティについて考えてみましょう。 Person には、アクティブステータスの重複レコードがあってはなりません。 つまり、personNumberisActiveで構成されるキーの値が重複することはありません。 ここでは、複数の列にまたがる一意の制約を追加する必要があります。

JPAは、@UniqueConstraintアノテーションを使用してこれを実現するのに役立ちます。 uniqueConstraints属性の下の@Tableアノテーションで使用します。 列の名前を指定することを忘れないでください。

@Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "personNumber", "isActive" }) })

スキーマが生成されたら、それを検証できます。

[main] DEBUG org.hibernate.SQL -
    alter table Person add constraint UK5e0bv5arhh7jjhsls27bmqp4a unique (personNumber, isActive)

ここで注意すべき点の1つは、名前を指定しない場合、それはプロバイダーによって生成された値であるということです。 JPA 2.0以降、一意の制約に名前を付けることができます。

@Table(uniqueConstraints = { @UniqueConstraint(name = "UniqueNumberAndStatus", columnNames = { "personNumber", "isActive" }) })

そして、同じことを検証できます。

[main] DEBUG org.hibernate.SQL -
    alter table Person add constraint UniqueNumberAndStatus unique (personNumber, isActive)

ここでは、一連の列に一意の制約を追加しました。 複数の一意の制約を追加することもできます。つまり、複数の列セットに一意の制約を追加できます。 次のセクションでそれを行います。

5.3. 単一のエンティティに対する複数の一意の制約

テーブルには複数の一意の制約を設定できます。前のセクションでは、複合キーに一意の制約を定義しました:personNumberおよびisActiveステータス。 このセクションでは、securityNumberdepartmentCodeの組み合わせに制約を追加します。

一意のインデックスを収集して、一度に指定しましょう。 これを行うには、 @UniqueConstraint アノテーションを中かっこで繰り返し、コンマで区切ります。

@Table(uniqueConstraints = {
   @UniqueConstraint(name = "UniqueNumberAndStatus", columnNames = {"personNumber", "isActive"}),
   @UniqueConstraint(name = "UniqueSecurityAndDepartment", columnNames = {"securityNumber", "departmentCode"})})

次に、ログを確認して、制約を確認しましょう。

[main] DEBUG org.hibernate.SQL -
    alter table Person add constraint UniqueNumberAndStatus unique (personNumber, isActive)
[main] DEBUG org.hibernate.SQL -
   alter table Person add constraint UniqueSecurityAndDepartment unique (securityNumber, departmentCode)

これまで、同じエンティティ内のフィールドに一意の制約を定義していました。 ただし、場合によっては、他のエンティティからフィールドを参照している可能性があり、それらのフィールドの一意性を確認する必要があります。 これについては、次のセクションで説明します。

6. 参照テーブル列に対する一意の制約

相互に関連する2つ以上のテーブルを作成する場合、それらは多くの場合、一方のテーブルの列が他方のテーブルの主キーを参照することによって関連付けられます。 その列は「外部キー」と呼ばれます。 たとえば、PersonおよびAddressエンティティは、addressIdフィールドを介して接続されます。 したがって、addressIdは参照テーブル列として機能します。

参照される列に一意の制約を定義できます最初に単一の列に実装し、次に複数の列に実装します。

6.1. 単一列の制約

Person エンティティには、Addressエンティティを参照するaddressフィールドがあります。 personには一意のアドレスが必要です。

それでは、Personaddressフィールドに一意の制約を定義しましょう。

@Column(unique = true)
private Address address;

次に、この制約を簡単に確認しましょう。

[main] DEBUG org.hibernate.SQL -
   alter table Person add constraint UK_7xo3hsusabfaw1373oox9uqoe unique (address)

次のセクションで説明するように、参照されるテーブルの列に複数の列の制約を定義することもできます。

6.2. 複数列の制約

列の組み合わせに一意の制約を指定できます。 前に述べたように、テーブル制約を使用してこれを行うことができます。

personNumberおよびaddress、に一意の制約を定義し、それをuniqueConstraints配列に追加しましょう。

@Entity
@Table(uniqueConstraints = 
  { //other constraints
  @UniqueConstraint(name = "UniqueNumberAndAddress", columnNames = { "personNumber", "address" })})

最後に、固有の制約を見てみましょう。

[main] DEBUG org.hibernate.SQL -
    alter table Person add constraint UniqueNumberAndAddress unique (personNumber, address)

7. 結論

一意の制約により、2つのレコードが1つの列または列のセットで同じ値を持つことはできません。

この記事では、JPAで一意の制約を定義する方法を学びました。 まず、固有の制約について少し要約しました。 次に、 @Column(unique = true)および @UniqueConstraint アノテーションについて説明し、それぞれ単一の列と複数の列に一意の制約を定義しました。

いつものように、この記事の例はGitHubから入手できます。