我有一个实体 Course
和一个实体 User
。类(class)和用户之间存在多对多关系,因为一个类(class)可以有很多用户,一个用户可以注册很多类(class)。在这两个实体中,我都在特定字段上放置了 @ManyToMany
注释,也就是说,在 Course
中,我有:
@ManyToMany
private List<RegisteredUser> members;
在 User
中我有:
@ManyToMany
private List<Course> coursesTaken;
现在,我知道这种多对多关系通常由第三个表表示。我还知道有注释 @JoinTable
允许我们这样做。我不知道是否应该在两个不同实体的两个字段上添加此注释 @JoinTable
。顺便说一句,如果我需要同时添加两者,名称需要匹配吗?
最佳答案
这实际上是一个很好的问题,它有助于理解“拥有”实体的概念,因为双方都不需要 @JoinTable
注释。如果你想防止双方都有 join tables
,这是一个好主意,那么你需要在一侧有一个 mappedBy=
元素。 @JoinTable
注释用于指定表名或映射关联的列。
Specifies the mapping of associations. It is applied to the owning side of an association.
是否有join table
由@ManyToMany
注释的mappedBy="name"
元素控制。 Javadoc for mappedBy for the ManyToMany
annotation says :
The field that owns the relationship. Required unless the relationship is unidirectional.
对于您在 Hibernate (5.0.9.Final) 中的(双向)示例,如果只有两个 @ManyToMany
注释并且没有 mappedBy=
元素,默认将有两个 Entity
表和两个 Join Tables
:
Hibernate: create table Course (id bigint not null, primary key (id))
Hibernate: create table Course_Member (Course_id bigint not null, members_id bigint not null, primary key (Course_id, members_id))
Hibernate: create table Member (id bigint not null, primary key (id))
Hibernate: create table Member_Course (Member_id bigint not null, courses_id bigint not null, primary key (Member_id, courses_id))
虽然这是说每个实体“拥有”它的ManyToMany
关系,但额外的join table
在典型用例中是多余的。但是,如果我决定让 Member
实体“拥有”关系,则我将 mappedBy=
元素添加到 Course
实体以指定它不拥有关系:
@ManyToMany(mappedBy="courses")
Set<Member> members;
将 @JoinTable(name="Member_Course")
添加到 Member
实体不会改变任何东西:它只是将表命名为与它本来命名的相同反正。
由于 Course
实体不再拥有它的 ManyToMany
关系,因此不会创建额外的 JoinTable
:
Hibernate: create table Course (id bigint not null, primary key (id))
Hibernate: create table Member (id bigint not null, primary key (id))
Hibernate: create table Member_Course (members_id bigint not null, courses_id bigint not null, primary key (members_id, courses_id))
这对开发人员很重要,因为他或她必须明白,除非将关系添加到拥有实体(在本例中为 Member
实体),否则任何关系都不会持久。但是,由于这是双向关系,开发人员应该向 Member.courses
添加 both Course
和 Member
到 Course.members
无论如何。
因此,如果您有一个双向
ManyToMany
关系,这意味着您在涉及的两个实体上都有ManyToMany
,那么您应该添加一个mappedBy="name"
在其中之一上,以避免出现冗余的 join table
。因为它是双向的,所以我认为将 owning
实体放在哪一边并不重要。与往常一样,启用 sql 日志并查看数据库中发生的情况始终是个好主意:
引用资料:
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()? .
关于java - @JoinTable 是否应该在@ManyToMany 关系的两边指定?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36803306/