为什么需要拥有方的概念:
双向关系拥有方的想法来自这样一个事实,即在关系数据库中没有像对象那样的双向关系。在数据库中,我们只有单向关系——外键。
“拥有方”这个名称的原因是什么?
Hibernate 跟踪的关系的拥有方是拥有数据库中外键的关系的一方。
拥有方的概念解决了什么问题?
以两个实体的映射为例没有声明拥有方:
@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 的角度来看,这个映射定义的不是一个双向关系,而是两个独立的单向关系。
映射不仅会创建表PERSONS 和ID_DOCUMENTS,还会创建第三个关联表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)
)
只注意ID_DOCUMENTS 上的主键pk。在这种情况下,Hibernate 独立跟踪关系的两侧:如果您将文档添加到关系 Person.idDocuments,它会在关联表 PERSON_ID_DOCUMENTS 中插入一条记录。
另一方面,如果我们调用idDocument.setPerson(person),我们会更改表ID_DOCUMENTS 上的外键person_id。 Hibernate 正在数据库上创建两个单向(外键)关系,以实现一个双向对象关系。
拥有方的概念如何解决问题:
很多时候,我们想要的只是表 ID_DOCUMENTS 上指向 PERSONS 的外键,而不是额外的关联表。
为了解决这个问题,我们需要配置 Hibernate 以停止跟踪关系 Person.idDocuments 上的修改。 Hibernate 应该只跟踪关系 IdDocument.person 的 other 端,为此我们添加 mappedBy:
@OneToMany(mappedBy="person")
private List<IdDocument> idDocuments;
mappedBy 是什么意思?
这意味着类似:“关系这一侧的修改已经映射为
关系 IdDocument.person 的另一端,所以不需要
在一个额外的表中单独跟踪它。”
是否有任何 GOTCHA、后果?
使用mappedBy,如果我们只调用person.getDocuments().add(document),ID_DOCUMENTS中的外键将不链接到新文档,因为这不是拥有/跟踪关系的一方!
要将文档链接到新人,您需要显式调用document.setPerson(person),因为这是关系的拥有方。
在使用mappedBy时,开发者有责任知道什么是拥有方,并更新关系的正确方以触发新关系在数据库中的持久化.