实现多对多的两种方式

在项目中,实体关系有一种是多对多关系。在最近的项目中,我学习了两种维护多对多关系的方式,在这里与大家分享一下。

场景描述

两个实体,角色和菜单,关系多对多。使用:Jpa的@ManyToMany注解。

一:简单实现

第一种的实现方法就是在字段上简单使用多对多注解。

1
2
3
4
5
6
7
@Entity
public class Role implements Serializable{
...
@ManyToMany
private Set<WebAppMenu> webAppMenus = new HashSet<WebAppMenu>();
...
}
1
2
3
4
5
6
7
@Entity
public class WebAppMenu extends BaseWebAppMenu {
...
@ManyToMany
private Set<Role> roles = new HashSet<>();
...
}

但是在使用这种方法的时候,还需要使用@ManyToMany注解的一个属性mappedBy,来声明维护中间表的一方。如果在这个时候不使用这个属性,就会出现生成两张中间表的现象。

1
2
3
4
5
6
7
@Entity
public class WebAppMenu {
...
@ManyToMany(mappedBy = "webAppMenus")
private Set<Role> roles = new HashSet<>();
...
}

这次我们在role这个字段上的@ManyTomany注解上使用mappedBy,将维护权交给对方,也就是说roles不能维护双方的关系,关系由WebAppMenus来维护。这样就只会生成一张中间表。

二:中间表类

这种方法我们会直接定义一个中间表实体,然后将多对多的双方都映射到这个表中,这样一来就不用关维护方到底是谁了。

1
2
3
4
5
6
7
8
9
10
11
12
13
@Entity
@Table(name = "web_app_menu_role")
public class WebAppMenuRole implements Serializable{
...
@ManyToOne
@JoinColumn(name = "role_id", insertable = false, updatable = false)
protected Role role;
@ManyToOne
@JoinColumn(name = "web_app_menu_id", insertable = false, updatable = false)
protected WebAppMenu webAppMenu;
...
}

这是我们定义的中间表类,在这里,中间表和另外的两个实体关系都是多对一的,然后在实体上声明一下表名(也就是我们的中间表):

1
@Table(name = "web_app_menu_role")

然后声明一下中间表中的字段名:

1
2
@JoinColumn(name = "role_id", insertable = false, updatable = false)
@JoinColumn(name = "web_app_menu_id", insertable = false, updatable = false)

在我们的两个实体中,实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
@Entity
public class WebAppMenu {
...
@ManyToMany
@JoinTable(
name = "web_app_menu_role",
joinColumns = @JoinColumn(name = "web_app_menu_id"),
inverseJoinColumns = @JoinColumn(name = "role_id")
)
private Set<Role> roles = new HashSet<>();
...
}
1
2
3
4
5
6
7
8
9
10
11
12
@Entity
public class Role implements Serializable{
...
@ManyToMany
@JoinTable(
name = "web_app_menu_role",
joinColumns = @JoinColumn(name = "role_id"),
inverseJoinColumns = @JoinColumn(name = "web_app_menu_id")
)
private Set<WebAppMenu> webAppMenus = new HashSet<WebAppMenu>();
...
}

关联的实体中依然使用@ManyToMany注解,然后再使用@JoinTable注解,声明将这两个字段映射到中间表里,并对应上面的字段名。

友情参考:https://en.wikibooks.org/wiki/Java_Persistence/ManyToMany

坚持原创技术分享,您的支持将鼓励我继续创作!