所有側の概念が必要な理由:
双方向リレーションシップの所有側の考え方は、リレーショナルデータベースにはオブジェクトの場合のような双方向リレーションシップがないという事実から来ています。データベースでは、外部キーという単一方向の関係のみがあります。
「所有側」という名前の理由は何ですか?
Hibernateによって追跡されるリレーションの所有側は、データベースで外部キーを所有するリレーションの側です。
所有側の概念が解決する問題は何ですか?
所有側を宣言せずにマップされた2つのエンティティの例を見てみましょう。
@Entity
@Table(name="PERSONS")
public class Person {
@OneToMany
private List<IdDocument> idDocuments;
}
@Entity
@Table(name="ID_DOCUMENTS")
public class IdDocument {
@ManyToOne
private Person person;
}
OOの観点からは、このマッピングは1つの双方向の関係ではなく、2つの別々の単方向の関係を定義します。
マッピングはテーブルPERSONS
とを作成するだけでなくID_DOCUMENTS
、3番目の関連テーブルも作成しますPERSONS_ID_DOCUMENTS
。
CREATE TABLE PERSONS_ID_DOCUMENTS
(
persons_id bigint NOT NULL,
id_documents_id bigint NOT NULL,
CONSTRAINT fk_persons FOREIGN KEY (persons_id) REFERENCES persons (id),
CONSTRAINT fk_docs FOREIGN KEY (id_documents_id) REFERENCES id_documents (id),
CONSTRAINT pk UNIQUE (id_documents_id)
)
主キーのみがpk
オンになっていることに注意してくださいID_DOCUMENTS
。この場合、Hibernateはリレーションの両側を個別に追跡しPerson.idDocuments
ますPERSON_ID_DOCUMENTS
。ドキュメントをリレーションに追加すると、関連付けテーブルにレコードが挿入されます。
一方、を呼び出すとidDocument.setPerson(person)
、テーブルの外部キーperson_idが変更されますID_DOCUMENTS
。Hibernateは、1つの双方向オブジェクトリレーションを実装するために、データベース上に2つの単方向(外部キー)リレーションを作成しています。
所有側の概念が問題を解決する方法:
私たちが望むものを何度だけ、テーブルの外部キーであるID_DOCUMENTS
に向けてPERSONS
、余分なアソシエーションテーブル。
これを解決するには、リレーションの変更の追跡を停止するようにHibernateを構成する必要がありますPerson.idDocuments
。Hibernateはリレーションの反対側のみを追跡する必要IdDocument.person
があります。そのためには、mapedByを追加します。
@OneToMany(mappedBy="person")
private List<IdDocument> idDocuments;
mapsByはどういう意味ですか?
つまり、「リレーションのこちら側の変更
は、リレーションIdDocument.personのもう一方の側ですでにマップされているため、ここで個別に追加のテーブルで追跡する必要はありません。」
GOTCHA、結果はありますか?
mappedByを使用すると、を呼び出すだけの場合person.getDocuments().add(document)
、外部キーin ID_DOCUMENTS
は新しいドキュメントにリンクされません。これは、関係の所有/追跡された側ではないためです。
新しい人に文書をリンクするには、明示的に呼び出す必要があるdocument.setPerson(person)
ことがあるので、所有側関係の。
mappedByを使用する場合、データベース内の新しいリレーションの永続化をトリガーするために、所有する側を把握し、リレーションの正しい側を更新するのは開発者の責任です。