答案 0 :(得分:13)
这实际上是一个很好的问题,它有助于理解“拥有”实体的概念。如果你想要防止双方(双向关系)拥有join tables
,这是一个好主意,那么你需要在一侧有一个mappedBy=
元素。
是否存在join table
由mappedBy="name"
注释的@ManyToMany
元素控制。 Javadoc for mappedBy for the ManyToMany
annotation says:
拥有这种关系的领域。除非关系是单向的,否则是必需的。
对于您的(双向)示例,如果只有两个@ManyToMany
注释且没有mappedBy=
元素,则默认情况下将有两个Entity
表和两个Join Tables
:< / p>
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
设置的连接表,那么您必须检查文档以查看哪一方“拥有”该关系。可能是双方都不拥有它,并且任何一方或任何一方都不会更新该实体。
参考文献:
What is the difference between Unidirectional and Bidirectional associations?
What does relationship owner means in bidirectional relationship?
What is the “owning side” in an ORM mapping?
Most efficient way to prevent an infinite recursion in toString()?
答案 1 :(得分:1)
mappedBy
链接双向关系的两边。您将mappedBy
放在关系的OWNER上,而不是基于某些记录有多少(也就是面向对象的设计)。您可以在任何JPA教程和文档中找到此信息。