- 在双向多对多关系中设置 MappedBy 的原因是什么?
- 当一张表有大量记录,而另一张表有少量记录时,mappedBy 放在哪一侧更好?
2 回答
这实际上是一个很好的问题,它有助于理解“拥有”实体的概念。如果你想防止双方(在双向关系中)有join tables
一个好主意,那么你需要mappedBy=
在一侧有一个元素。
是否有 ajoin table
由注解的mappedBy="name"
元素控制。注释的 mappedBy@ManyToMany
的Javadoc 说:ManyToMany
拥有关系的字段。除非关系是单向的,否则是必需的。
对于您的(双向)示例,如果只有两个@ManyToMany
注释而没有mappedBy=
元素,则默认将有两个Entity
表和两个Join Tables
:
Hibernate: create table SideA (id bigint not null, primary key (id))
Hibernate: create table SideA_SideB (sidea_id bigint not null, sidebs_id bigint not null, primary key (sidea_id, sidebs_id))
Hibernate: create table SideB (id bigint not null, primary key (id))
Hibernate: create table SideB_SideA (sideb_id bigint not null, sideas_id bigint not null, primary key (sideb_id, sideas_id))
虽然这是说每个实体都“拥有”它的ManyToMany
关系,但join table
在典型用例中额外的东西是多余的,Javadoc 说你需要一个mappedBy
注释。如果我决定让 SideA “拥有”关系,那么我将mappedBy=
元素添加到 SideB 实体以指定它不拥有关系:
@Entity
public class SideA {
@ManyToMany
Set<SideB> sidebs;
}
@Entity
public class SideB {
@ManyToMany(mappedBy="sidebs")
Set<SideA> sideas;
}
由于 SideB 实体不再拥有其关系,因此不会创建ManyToMany
额外的实体:JoinTable
Hibernate: create table SideA (id bigint not null, primary key (id))
Hibernate: create table SideB (id bigint not null, primary key (id))
Hibernate: create table SideA_SideB (sideas_id bigint not null, sidebs_id bigint not null, primary key (sideas_id, sidebs_id))
这对开发人员很重要,因为他或她必须了解,除非将其添加到拥有实体(在本例中为SideA
实体),否则不会保留任何关系。
因此,如果您有bidirectional
ManyToMany
关系,这意味着您ManyToMany
在涉及的两个实体上都有,那么您应该mappedBy="name"
根据 Javadoc 在其中一个上添加一个,以避免多余的join table
.
至于哪一方做拥有实体,没有正确的答案,这取决于你的系统认为什么是最好的。仅当条目放在拥有方时,这种关系才会持续存在,因此您必须问自己是否更常更改SideA's
列表或SideB's
列表。如果SideA
拥有关系,那么您可以通过在实例中添加或删除SideB
实例来更新关系,SideA
但如果您有一个想要持久的SideA
实例列表,则需要遍历列表并更改列表中的每个实例。SideB
SideA
与往常一样,启用 sql 日志并查看数据库中发生了什么总是一个好主意:
编辑:如果您有一个仅创建一个没有mappedBy
设置的连接表的持久性提供程序,那么您必须检查文档以查看哪一方“拥有”关系。可能是双方都没有或双方都拥有它,并且更新任何一方都不会保留实体。
参考:
mappedBy
链接双向关系的双方。您放置mappedBy
关系的所有者,而不是基于某物有多少记录(也称为面向对象设计)。您可以在任何 JPA 教程和文档中找到此信息。