拥有方 究竟是什么意思?一些映射示例( 一对多、一对一、多对一 )的解释是什么?
以下文本摘自Java EE 6 文档中对 @OneToOne的描述。 您可以在其中看到概念 拥有的一面 。
定义与另一个具有一对一多重性的实体的单值关联。通常不需要明确指定关联的目标实体,因为它通常可以从被引用的对象的类型中推断出来。如果关系是双向 的,非拥有方 必须使用 OneToOne 注解的 mappedBy 元素来指定拥有方的关系字段或属性。
为什么拥有方的概念是必要的:
双向关系拥有方的想法来自这样一个事实,即在关系数据库中没有像对象那样的双向关系。在数据库中,我们只有单向关系——外键。
“拥有方”这个名字的原因是什么?
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:
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) )
只注意主键pk。ID_DOCUMENTS在这种情况下,Hibernate 独立跟踪关系的两侧:如果您将文档添加到关系Person.idDocuments,它会在关联表中插入一条记录PERSON_ID_DOCUMENTS。
pk
Person.idDocuments
PERSON_ID_DOCUMENTS
另一方面,如果我们调用idDocument.setPerson(person),我们会更改 table 上的外键 person_id ID_DOCUMENTS。Hibernate 是在数据库上创建 两个 单向(外键)关系,以实现 一个 双向对象关系。
idDocument.setPerson(person)
拥有方的概念如何解决问题:
很多时候,我们想要的只是表上的外键,ID_DOCUMENTS而PERSONS不是额外的关联表。
为了解决这个问题,我们需要配置 Hibernate 以停止跟踪对关系的修改Person.idDocuments。Hibernate 应该只跟踪关系的 另一 端IdDocument.person,为此我们添加 mappedBy :
IdDocument.person
@OneToMany(mappedBy="person") private List<IdDocument> idDocuments;
mappedBy 是什么意思?
这意味着类似:“关系这一侧的修改已经被关系 IdDocument.person 的另一侧 映射 ,因此无需在额外的表中单独跟踪它。”
有任何问题,后果吗?
使用 mappedBy ,如果我们只调用person.getDocuments().add(document),外键 inID_DOCUMENTS将 不会 链接到新文档,因为这不是关系的拥有/跟踪的一面!
person.getDocuments().add(document)
要将文档链接到新人员,您需要显式调用document.setPerson(person),因为这是关系的 _ 拥有方_ 。
document.setPerson(person)
使用 mappedBy 时,开发人员有责任知道拥有方是什么,并更新关系的正确方以触发数据库中新关系的持久性。