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