本篇介绍多对多的单向关联,多对多的处理方式是,有一张中间表,中间表保存两个多方之间的关系。首先来看实际应用场景:在之前开发的系统中,应用了基于角色的控制访问,也就是RBAC模型,一个用户可能存在多种角色,一种角色也可能有多个用户,所以用户和角色之间是一个多对多的关系。实体:用户(User),具有如下属性:Id,名称(name),角色列表(roles);实体:角色(Role),具有如下属性:Id,名称(name);既然是单项关联,所以就可以从当前用户,读取到具有的角色列表,而不能从当前角色获取用户列表。
下面来看表结构:
中间表user_role中,有一个字段userId作为外键指向了user表的id,同样,有一个字段roleId也是作为外键指向了role表的id,这样就保存了两个多方之间的关系。
下面来看实体类的书写:
import java.util.HashSet;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
@Entity
public class User {
private Integer id;
private String name;
private Set roles = new HashSet();
public User() {
super();
}
public User(Integer id, String name) {
super();
this.id = id;
this.name = name;
}
@Id
@GeneratedValue
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@ManyToMany
@JoinTable(name="user_role",
joinColumns={@JoinColumn(name="userId")},
inverseJoinColumns={@JoinColumn(name="roleId")})
public Set getRoles() {
return roles;
}
public void setRoles(Set roles) {
this.roles = roles;
}
}
用一个Set集合来保存User中的Role列表,@ManyToMany表示这是一个多对多关系@JoinTable用来设置中间表,name=”user_role”中间表的名称,joinColumns={@JoinColumn(name=”userId”)},设置当前实体在中间表中的映射,也就是说在中间表中设置一个字段叫userId,指向当前user表的id;inverseJoinColumns={@JoinColumn(name=”roleId”)}设置对方实体在中间中的映射,也就是说在中间表中设置一个字段roleId,指向对方表(role表)的id。
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
@Entity
public class Role {
private Integer id;
private String name;
public Role() {
super();
}
public Role(Integer id, String name) {
super();
this.id = id;
this.name = name;
}
@Id
@GeneratedValue
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
role表就没什么要介绍的了。
下面来看CRUD测试:
首先是添加数据的测试,testCreate()
@Test
public void testCreate(){
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
User u1 = new User();
u1.setName("admin");
User u2 = new User();
u2.setName("wan");
Role r1 = new Role();
r1.setName("超级管理员");
Role r2 = new Role();
r2.setName("普通用户");
Set roleSet1 = new HashSet();
roleSet1.add(r1);
roleSet1.add(r2);
u1.setRoles(roleSet1);
Set roleSet2 = new HashSet();
roleSet2.add(r2);
u2.setRoles(roleSet2);
session.saveOrUpdate(u1);
session.saveOrUpdate(u2);
session.saveOrUpdate(r1);
session.saveOrUpdate(r2);
session.getTransaction().commit();
}
新建一个u1,叫admin,一个u2,叫wan
新建一个r1,叫“超级管理员”,一个r2,叫“普通用户”
new一个角色集合,包含了r1和r2,设置给u1
new一个角色集合,只包含r2,设置给u2
将上述内容,保存到数据库,就是本测试用例。
那么,在数据库中,中间表应该有三条数据
userId roleId
1 1
1 2
2 2
结果如下:
接下来进行读取数据的测试,testRead()
@Test
public void testRead(){
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
User user = (User) session.load(User.class, 1);
System.out.println(user.getName());
for (Role r:user.getRoles()){
System.out.println(r.getName());
}
session.getTransaction().commit();
}
结果如下:
Hibernate:
select
user0_.id as id6_0_,
user0_.name as name6_0_
from
User user0_
where
user0_.id=?
admin
Hibernate:
select
roles0_.userId as userId1_,
roles0_.roleId as roleId1_,
role1_.id as id7_0_,
role1_.name as name7_0_
from
user_role roles0_
left outer join
Role role1_
on roles0_.roleId=role1_.id
where
roles0_.userId=?
超级管理员
普通用户
下面是修改操作,testUpdate()
@Test
public void testUpdate(){
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
User user = (User) session.load(User.class, 2);
user.setName("administrator");
Role role = (Role) session.load(Role.class, 1);
Set roleSet = new HashSet();
roleSet.add(role);
user.setRoles(roleSet);
session.saveOrUpdate(user);
session.getTransaction().commit();
}
将用户为wan读取出来,修改名字为administrator,将普通用户的角色修改为超级管理员,结果如下:
最后是删除操作,testDelete()
@Test
public void testDelete(){
Session session = sessionFactory.getCurrentSession();
session.beginTransaction();
User user = (User) session.load(User.class, 2);
user.setRoles(null);
session.delete(user);
session.getTransaction().commit();
}
下一篇介绍多对多的双向关联,希望对你有所帮助