Ang*_*ity 170
为什么必须拥有一个拥有方的概念:
双向关系的拥有方的想法来自这样的事实:在关系数据库中没有像对象那样的双向关系.在数据库中,我们只有单向关系 - 外键.
名称"拥有方"的原因是什么?
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;
}
Run Code Online (Sandbox Code Playgroud)
从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)
)
Run Code Online (Sandbox Code Playgroud)
注意主键pk上ID_DOCUMENTS唯一的.在这种情况下,Hibernate独立地跟踪关系的两端:如果将文档添加到关系Person.idDocuments,它会在关联表中插入记录PERSON_ID_DOCUMENTS.
另一方面,如果我们调用idDocument.setPerson(person),我们在表上更改外键person_id ID_DOCUMENTS.Hibernate 在数据库上创建了两个单向(外键)关系,以实现一个双向对象关系.
拥有方的概念如何解决问题:
很多时候,我们要的是上表只是一个外键ID_DOCUMENTS对PERSONS和额外的关联表.
为了解决这个问题,我们需要配置Hibernate来停止跟踪关系的修改Person.idDocuments.Hibernate应该只跟踪关系的另一面IdDocument.person,为此我们添加mappedBy:
@OneToMany(mappedBy="person")
private List<IdDocument> idDocuments;
Run Code Online (Sandbox Code Playgroud)
它是什么意思mappedBy?
这意味着:"关系的这一侧的修改已经 被关系IdDocument.person的另一侧映射,所以不需要在额外的表中单独跟踪它."
是否有任何GOTCHA,后果?
使用mappedBy,如果我们只调用person.getDocuments().add(document),外键ID_DOCUMENTS将不会链接到新文档,因为这不是关系的拥有/跟踪方!
要将文档链接到新人,您需要显式调用document.setPerson(person),因为这是关系的拥有方.
使用mappedBy时,开发人员有责任了解拥有方是什么,并更新关系的正确方面,以便触发数据库中新关系的持久性.
Jac*_*ack 135
您可以想象拥有方是指向另一方的实体.在你的摘录中,你有一对一的关系.由于它是一个对称关系,如果对象A与对象B相关,那么你最终会得到它,反之亦然.
这意味着保存到对象A中对对象B的引用并保存在对象B中对对象A的引用将是多余的:这就是为什么您选择哪个对象"拥有"另一个对象具有对它的引用.
当你有一对多的关系时,与"many"部分相关的对象将是拥有者,否则你将不得不将来自单个对象的许多引用存储到众多.为了避免这种情况,第二类中的每个对象都将有一个指向它们所引用的单个对象的指针(因此它们是拥有方).
对于多对多关系,因为无论如何您都需要一个单独的映射表,因此不会有任何拥有方.
总之,拥有方是指对方的实体.
我将非常简短地解释这一点。“拥有”意味着本身带有外键列。换句话说,它拥有这种关系。许多人误解了“拥有”这个词。他们认为拥有方才是主要方。但是当我们查看它时,具有外键列的表是链接侧。例如:让我们考虑一下 Person 和 Adress 以及它们之间的关系 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;
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,Person 有 adress_id fk 列,该列链接到主键列的地址。
一般来说,您可能会想为什么我需要拥有方?要理解这一点,您需要了解数据库规则。例如,假设您不想使用拥有方并将所有数据存储在一个表中,这意味着实施糟糕的数据库实践。所以我假设您现在了解每个实体应该将自己的数据存储在自己的表中。现在他们要求您在视图部分显示此人及其地址。如果没有拥有方,你会怎么做?您可能必须为每个实体创建 2 个查询,对吧?在这里,您也犯了一个错误的 DML。您可以使用 编写 1 个查询,而不是编写 2 个查询JOIN。JOIN 与我们定义的拥有方一起工作,没有它们,我们无法从另一表中选择属于一个表的数据。ORM 还为您提供了一种更舒适的方式,通过实体使用基本的 java 代码,而无需使用数据库。就是这样。
| 归档时间: |
|
| 查看次数: |
32784 次 |
| 最近记录: |