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