ORM映射中的“拥有方”是什么?
拥有方意味着什么? 什么是一些映射实例的解释( 一对多,一对一,多对一 )?
以下文字摘自Java EE 6文档中@OneToOne的描述。 你可以看到它拥有一面的概念。
定义一个单值关联到另一个具有一对一多重性的实体。 通常不需要显式指定关联的目标实体,因为通常可以从被引用的对象的types中推断出来。 如果关系是双向的, 则非拥有方必须使用OneToOne批注的mappedBy元素来指定拥有方的关系字段或属性。
你可以想象, 拥有的一方是指另一方的实体。 在你的节选中,你有一个一对一的关系。 因为它是一个对称关系,所以如果对象A与对象B有关系,那么反之亦然。
这意味着保存到对象A中的对象B的引用和保存在对象B中的对象A的引用将是多余的:这就是为什么你select哪个对象“拥有”另一个对象的引用。
当你有一对多的关系时,与“多”部分相关的对象将成为拥有者的一方,否则你将不得不从多个对象中存储许多引用。 为了避免这种情况,第二类中的每个对象都会有一个指向它们所指向的单个对象的指针(所以它们是拥有者的一方)。
对于多对多的关系,由于无论如何你都需要一个单独的映射表,所以不会有任何拥有方。
总而言之, 拥有的一方是指另一方的实体。
为什么拥有一方的概念是必要的:
双向关系拥有一方的想法来自这样一个事实,即在关系数据库中不存在像对象一样的双向关系。 在数据库中,我们只有单向关系 – 外键。
“拥有一方”这个名字的原因是什么?
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的angular度来看,这个映射不是定义一个双向关系,而是定义两个不同的单向关系。
映射不仅会创build表ID_DOCUMENTS
和ID_DOCUMENTS
,还会创build第三个关联表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
插入一条logging。
另一方面,如果我们调用idDocument.setPerson(person)
,则更改表ID_DOCUMENTS
上的外键ID_DOCUMENTS
。 Hibernate在数据库上创build两个单向(外键)关系,实现一个双向对象关系。
拥有方的概念如何解决问题:
很多时候我们想要的仅仅是ID_DOCUMENTS
表中的一个外键,用于表示人员和附加关联表。
为了解决这个问题,我们需要configurationHibernate来停止跟踪Person.idDocuments
关系的修改。 Hibernate应该只跟踪关系IdDocument.person
的另一端, IdDocument.person
我们添加mappedBy :
@OneToMany(mappedBy="person") private List<IdDocument> idDocuments;
这是什么意思映射?
这意味着像这样:“关系的这一方的修改已经被映射到关系IdDocument.person的另一端,所以不需要在一个额外的表中单独追踪它。
有没有GOTCHA,后果?
使用mappedBy ,如果我们只调用person.getDocuments().add(document)
, ID_DOCUMENTS
的外键将不会链接到新文档,因为这不是关系的拥有/追踪的一面!
要将文档链接到新的人员,您需要显式调用document.setPerson(person)
,因为这是关系的拥有方 。
当使用mappedBy时 ,开发人员有责任知道什么是拥有方,并且更新关系的正确方面以触发数据库中新关系的持久性。