JPAにおける一対一の関係

1.はじめに

このチュートリアルでは、JPAで一対一のマッピングを作成するさまざまな方法について説明します。

Hibernateフレームワークの基本的な知識が必要なので、詳細な背景についてはhttps://www.baeldung.com/hibernate-5-spring[Guide to Hibernate 5 with Spring]をご覧ください。

2.説明

ユーザー管理システムを構築中で、上司から各ユーザーのメールアドレスを保存するように依頼されたとします。ユーザーには1つのメールアドレスがあり、1つのメールアドレスには1人のユーザーしか関連付けられていません。

これは、1対1の関係の例です。この場合、 _ user address _ entityの間の関係です。

次のセクションで、これをどのように実装できるかを見てみましょう。

3.外部キーを使う

3.1. 外部キーを使ったモデリング

次のhttps://en.wikipedia.org/wiki/Entity%E2%80%93relationship__model[ER図]を見てみましょう。これは外部キーベースの1対1マッピングを表しています。

この例では、 users __address id __columnは、https://en.wikipedia.org/wiki/Foreign key[foreign key]から address までです。

3.2. JPAで外部キーを使用して実装する

まず、 __ User __クラスを作成し、適切に注釈を付けます。

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long id;
   //...

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "address__id", referencedColumnName = "id")
    private Address address;

   //... getters and setters
}
  • __ @ OneToOne annotation ** を関連エンティティフィールド Address__に配置します。

また、 address の主キーに対応する users テーブルの列の名前を設定するには、https://www.baeldung.com/jpa-join-column[the JoinColumn __annotation] を配置する必要があります。表。名前を入力しないと、Hibernateはhttp://docs.jboss.org/hibernate/jpa/2.2/api/javax/persistence/JoinColumn.html[いくつかの規則に従って]デフォルトの名前を選択します。

最後に、次のエンティティでは、 __ @ JoinColumn アノテーションを使用していないことに注意してください。これは、外部キーの関係の 側にのみ必要なためです。簡単に言うと、外部キーカラムが @ JoinColumn アノテーションを取得した人は誰でも ダウン__します。

__Address __entityは、もう少し単純です。

@Entity
@Table(name = "address")
public class Address {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long id;
   //...

    @OneToOne(mappedBy = "address")
    private User user;

   //... getters and setters
}

__ @ OneToOne アノテーションもここに配置する必要があります。これは、https://docs.oracle.com/cd/E19798-01/821-1841/bnbqj/index.html[双方向の関係]であるためです。 関係の住所側を 非所有側と呼びます。

4.共有主キーを使う

4.1. 共有主キーを使用したモデリング

この戦略では、新しい列 __address idを作成する代わりに、 address table の主キー __column (user id) __users __テーブルへの外部キーとしてマークします。

これらのエンティティは1対1の関係にあるという事実を利用して、ストレージスペースを最適化しました。

4.2. JPAで共有主キーを使用して実装する

私たちの定義はほんの少しだけ変化することに注意してください。

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long id;

   //...

    @OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
    private Address address;

   //... getters and setters
}
@Entity
@Table(name = "address")
public class Address {

    @Id
    @Column(name = "id")
    private Long id;

   //...

    @OneToOne
    @MapsId
    private User user;

   //... getters and setters
}
  • @ MapsId は、Hibernateに addressの id 列を主キーと外部キーの両方として使用するよう指示します。 また、 Address __entityの @ Id 列に注意してください。 @ GeneratedValue __annotation を使用しなくなりました。

外部キーが __address テーブルに存在するため、 mappedBy 属性は User __クラスに移動しました。

5.結合テーブルを使う

1対1マッピングには、 Optional Mandatory の2種類があります。

これまでのところ、義務的な関係しか見ていません。

それでは、従業員がワークステーションに関連付けられたとしましょう。 1対1ですが、従業員がワークステーションを持っていない場合もあります。

5.1. 結合テーブルを使用したモデリング

私たちが今まで議論してきた戦略は今まで オプションの関係を扱うためにカラムにnull値を入れることを強制しました

通常、結合テーブルを検討するときは、https://www.baeldung.com/jpa-many-to-many[many-to-many relationship]を検討します。これらのnull値を排除するのに役立ちます。**

さて、関係があるときはいつでも、 __ emp workstation __テーブルにエントリを作成し、nullを __完全に避けます。

5.2. JPAでの結合テーブルを使用した実装

最初の例では __ @ JoinColumnを使用しました。 今度は、 @ JoinTable__を使用します。

@Entity
@Table(name = "employee")
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long id;

   //...

    @OneToOne(cascade = CascadeType.ALL)
    @JoinTable(name = "emp__workstation",
      joinColumns = { @JoinColumn(name = "employee__id", referencedColumnName = "id") },
      inverseJoinColumns = { @JoinColumn(name = "workstation__id", referencedColumnName = "id") })
    private WorkStation workStation;

   //... getters and setters
}
@Entity
@Table(name = "workstation")
public class WorkStation {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id")
    private Long id;

   //...

    @OneToOne(mappedBy = "workStation")
    private Employee employee;

   //... getters and setters
}

@ JoinTable は、関係を維持しながら結合テーブル方式を採用するようHibernateに指示します。

また、結合テーブルアノテーションを使用することを選択したため、 __従業員 __がこの関係の所有者です。

6.まとめ

このチュートリアルでは、JPAとHibernateで1対1の関連付けを維持するさまざまな方法と、それぞれをいつ使用するかを学びました。

このチュートリアルのソースコードはhttps://github.com/eugenp/tutorials/tree/master/persistence-modules/hibernate5[GitHubに載っています]をご覧ください。