JPAの複合主キー

1. 前書き

このチュートリアルでは、複合主キーとJPAの対応するアノテーションについて学習します。

2. 複合主キー

複合主キー(複合キーとも呼ばれる)は、2つ以上の列を組み合わせてテーブルの主キーを形成するものです。
JPAには、複合キーを定義する2つのオプションがあります:_ @ IdClass_および_ @ EmbeddedId_アノテーション。
*複合主キーを定義するには、いくつかのルールに従う必要があります*
  • 複合主キークラスはパブリックである必要があります

  • 引数なしのコンストラクタが必要です

  • _equals()_および_hashCode()_メソッドを定義する必要があります

  • _Serializable_でなければなりません

3. _IdClass_アノテーション

_Account_というテーブルがあり、複合キーを形成する_accountNumber、accountType –_の2つの列があるとします。 次に、JPAでマッピングする必要があります。
JPA仕様に従って、これらの主キーフィールドを持つ_AccountId_クラスを作成しましょう。
public class AccountId implements Serializable {
    private String accountNumber;

    private String accountType;

    // default constructor

    public AccountId(String accountNumber, String accountType) {
        this.accountNumber = accountNumber;
        this.accountType = accountType;
    }

    // equals() and hashCode()
}
次に、_AccountId_クラスをエンティティ_Account_に関連付けましょう。
そのためには、エンティティに_https://www.baeldung.com/hibernate-identifiers [@IdClass] _注釈を付ける必要があります。 また、エンティティ_Account_の_AccountId_ classからフィールドを宣言し、それらに_ @ Id_の注釈を付ける必要があります。
@Entity
@IdClass(AccountId.class)
public class Account {
    @Id
    private String accountNumber;

    @Id
    private String accountType;

    // other fields, getters and setters
}

4. _EmbeddedId_アノテーション

_ @ EmbeddedId_は、_ @ IdClass_アノテーションの代替です。
_title_と_language_を主キーフィールドとして_Book_の情報を保持する必要がある別の例を考えてみましょう。
この場合、主キークラス* _BookId、_に_ @ Embeddable_ *の注釈を付ける必要があります。
@Embeddable
public class BookId implements Serializable {
    private String title;
    private String language;

    // default constructor

    public BookId(String title, String language) {
        this.title = title;
        this.language = language;
    }

    // getters, equals() and hashCode() methods
}
次に、_https://www.baeldung.com/jpa-many-to-many [@EmbeddedId] _を使用して、このクラスを_Book_エンティティに埋め込む必要があります。
@Entity
public class Book {
    @EmbeddedId
    private BookId bookId;

    // constructors, other fields, getters and setters
}

5. _ @ IdClass_ vs _ @ EmbeddedId_

先ほど見たように、これら2つの違いは、_ @ IdClass_では、_AccountId_で1回、_Account._で1回、列を2回指定する必要があったことです。
ただし、他にもいくつかのトレードオフがあります。
*たとえば、これらの異なる構造は、作成するJPQLクエリに影響します。*
たとえば、_ @ IdClass_を使用すると、クエリは少し単純になります。
SELECT account.accountNumber FROM Account account
_ @ EmbeddedId_を使用すると、さらに1つのトラバーサルを行う必要があります。
SELECT book.bookId.title FROM Book book
また、* _ @ IdClass_は、**変更できない複合キークラスを使用している場所で非常に役立ちます。*
最後に、複合キーの部分に個別にアクセスする場合、_ @ IdClass、_を使用できますが、*完全な識別子をオブジェクトとして頻繁に使用する場所では、_ @ EmbeddedId_が優先されます。*

6. 結論

この簡単な記事では、JPAの複合主キーについて説明します。
いつものように、この記事の完全なコードはhttps://github.com/eugenp/tutorials/tree/master/persistence-modules/java-jpa[Githubで発見]です。