拥有方到底是什么意思? 用一些映射例子(一对多,一对一,多对一)解释一下?
以下文本摘自 JavaEE6文档中的 @ OneToOne 描述。您可以在其中看到 拥有方的概念。
将单值关联定义为 一对一的另一个实体 多样性。这是不正常的 指定相关的 目标实体,因为它可以 通常是从... 的类型推断出来的 被引用的对象。如果 关系是双向的 非所有方 必须使用 mappedBy OneToOne 注释的元素添加到 指定关系字段或 拥有方的财产。
可以想象,拥有一方是具有对另一个 拥有一方的引用的实体。在你的节选中,你们是一对一的关系。因为它是 对称的关系,所以如果对象 A 与对象 B 相关,那么反之亦然。
这意味着在对象 A 中保存对象 B 的引用,在对象 B 中保存对象 A 的引用将是多余的: 这就是为什么您选择哪个对象“拥有”另一个对象的引用。
当您有一个一对多关系时,与“多”部分相关的对象将是所有方,否则您将不得不存储从单个对象到多个对象的多个引用。为了避免这种情况,第二个类中的每个对象都将有一个指向它们引用的单个对象的指针(因此它们是所有者一方)。
对于多对多关系,因为无论如何都需要一个单独的映射表,所以不会有任何所有方。
总而言之,拥有一方是具有对另一个 拥有一方的引用的实体。
为什么拥有一方的概念是必要的:
双向关系的拥有方的概念来自于这样一个事实,即在关系数据库中没有像对象那样的双向关系。在数据库中,我们只有单向关系-外键。
“拥有一方”这个名字的原因是什么?
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; }
从面向对象的角度来看,这种映射定义的不是一个双向关系,而是 二独立的单向关系。
这个映射不仅会创建表 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) )
注意,只有 ID_DOCUMENTS上的主键 pk。在这种情况下,Hibernate 独立地跟踪关系的两端: 如果向关系 Person.idDocuments添加一个文档,它将在关联表 PERSON_ID_DOCUMENTS中插入一条记录。
pk
Person.idDocuments
PERSON_ID_DOCUMENTS
另一方面,如果我们调用 idDocument.setPerson(person),我们将更改表 ID_DOCUMENTS上的外键 person _ id。Hibernate 在数据库上创建 二单向(外键)关系,以实现 一双向对象关系。
idDocument.setPerson(person)
拥有一方的概念如何解决这个问题:
很多时候,我们想要的只是表 ID_DOCUMENTS上面向 PERSONS的一个外键,而不是额外的关联表。
为了解决这个问题,我们需要配置 Hibernate 来停止跟踪关系 Person.idDocuments上的修改。Hibernate 应该只跟踪关系 IdDocument.person的 其他端,为此我们添加 地图:
IdDocument.person
@OneToMany(mappedBy="person") private List<IdDocument> idDocuments;
地图是什么意思?
这意味着: “关系的这一侧的修改已经 < strong > Maps By 关系 IdDocument.person 的另一端,因此不需要 分开放在另一张桌子上。”
有什么后果吗?
使用 地图,如果我们只调用 person.getDocuments().add(document),ID_DOCUMENTS中的外键将 没有链接到新的文档,因为这不是关系的拥有/跟踪一侧!
person.getDocuments().add(document)
要将文档链接到新用户,需要显式调用 document.setPerson(person),因为它是关系的 拥有方。
document.setPerson(person)
在使用 地图时,开发人员有责任知道所属方是什么,并更新关系的正确一侧,以触发数据库中新关系的持久性。
双向关系必须遵循以下规则。
双向关系的反向端必须通过使用@OneToOne、@OneTomany 或@ManyTomany 注释的 mappedBy 元素来引用其所属端。MappedBy 元素指定作为关系所有者的实体中的属性或字段。
多对一双向关系的多边不能定义 mappedBy 元素
对于一对一的双向关系,拥有方对应于包含相应外键的方。
对于多对多双向关系,任何一方都可能是拥有方。
这很有帮助,我支持这个讨论
特别是我正在寻找以下用例在医院管理系统。 病人-> 病人病史 1.病人不依赖于病人的病史,即只有在第一次病人访问医院时,他的病史必须加上。 2.在随后的访问中,历史记录被添加到历史表中,但是需要一个对 Patientid 的引用。因此,这里的外键是 PatientHistory 表中的外键,所属方是 PatientHistory
因此,这种关系必须建模为患者实体中的“患者”映射的双向 OneTomany。每个实体相互引用。
我将简要地解释一下这个问题。“ Owning”表示本身携带外键列。换句话说,它拥有这种关系。许多人误解了“拥有”这个词。他们认为所有者党是主要党派。但是当我们查看它时,带有外键列的表是链接端。例如: 让我们考虑 Person 和 Address 以及它们之间的关系 OneToOne
@Data @Entity public class Person { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; @OneToOne @JoinColumn(name = "adress_id") private Adress adress; } @Data @Entity public class Adress { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @OneToOne(mappedBy = "adress") private Person person; }
在这种情况下,Person 有 address _ id fk 列,它链接了主键列的 Address。
一般来说,你可能会想,为什么我需要拥有的一面?要理解这一点,您需要了解数据库规则。例如,假设您不希望在一个表中使用拥有方和所有数据存储,这意味着实现了一个糟糕的数据库实践。因此,我假设您现在理解了每个实体应该在其自己的表中存储自己的数据。现在他们要求您在视图部分显示 Person 和他的 Address。如果没有拥有方,你会怎么做?您可能必须为每个实体创建两个查询,对吗?在这里,您也做了一个糟糕的 DML。您可以使用 JOIN编写1个查询,而不是编写2个查询。JOIN 与我们定义的拥有方的工作,如果没有它们,我们就不能从另一个表中选择属于一个表的数据。ORM 还为您提供了一种更舒适的方法,即通过实体使用基本的 Java 代码而不使用数据库。就是这样。
JOIN