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に載っています]をご覧ください。