一. 创建与数据库对应的封装类
User:
@Entity //实体类
@Table(name = "sys_user") //实体类对应数据库表名
public class User {
@Id //主键
@GeneratedValue(strategy = GenerationType.IDENTITY) //主键自增
@Column(name="user_id") //数据库对应列名
private Long userId;
@Column(name="user_name")
private String userName;
@Column(name="age")
private Integer age;
/**
* 配置用户到角色的多对多关系
* 配置多对多的映射关系
* 1.声明表关系的配置
* @ManyToMany(targetEntity = Role.class) //多对多
* targetEntity:代表对方的实体类字节码
* 2.配置中间表(包含两个外键)
* @JoinTable
* name: 中间表的名称
* joinColumns:配置当前对象在中间表的外键
* @JoinColumn的数组
* name:外键名
* referencedColumnName:参照的主表的主键名
* inverseJoinColumns:配置对方对象在中间表的外键
*/
@ManyToMany(targetEntity = Role.class)
@JoinTable(name = "sys_user_role", //中间表
//joinColumns, 当前对象在中间表中的外键
joinColumns = {@JoinColumn(name = "sys_user_id", referencedColumnName = "user_id")},
//inverseJoinColumns,对方对象在中间表的外键
inverseJoinColumns = {@JoinColumn(name = "sys_role_id", referencedColumnName = "role_id")}
)
private Set<Role> roles = new HashSet();
//getter setter 方法....
//toString() 方法....
}
Role:
@Entity //实体类
@Table(name = "sys_role") //实体类对应数据库表名
public class Role {
@Id //主键
@GeneratedValue(strategy = GenerationType.IDENTITY) //主键自增
@Column(name = "role_id") //数据库对应列名
private Long roleId;
@Column(name = "role_name")
private String roleName;
@ManyToMany(targetEntity = User.class)
@JoinTable(name = "sys_user_role", //中间表
//joinColumns, 当前对象在中间表中的外键
joinColumns = {@JoinColumn(name = "sys_role_id", referencedColumnName = "role_id")},
//inverseJoinColumns,对方对象在中间表的外键
inverseJoinColumns = {@JoinColumn(name = "sys_user_id", referencedColumnName = "user_id")}
)
private Set<User> users = new HashSet();
//getter setter 方法....
//toString() 方法....
}
二. 创建符合 SpringDataJpa 的 dao 层接口规范
UserDao:
public interface UserDao extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {
}
RoleDao:
public interface RoleDao extends JpaRepository<Role, Long>, JpaSpecificationExecutor<Role> {
}
三. 编写测试类
编写测试类框架:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class ManyToManyTest {
@Autowired
private UserDao userDao;
@Autowired
private RoleDao roleDao;
}
1. 保存一个用户的同时保存该用户所关联的角色
@Test
@Transactional
@Rollback(false)
public void testAdd() {
//创建一个用户
User user = new User();
user.setUserName("小李");
user.setAge(18);
//用户关联的角色
Role role = new Role();
role.setRoleName("java程序员");
//配置用户到角色关系,可以对中间表中的数据进行维护
user.getRoles().add(role);
//配置角色到用户的关系,可以对中间表的数据进行维护
role.getUsers().add(user);
userDao.save(user);
roleDao.save(role);
}
运行时, 会对中间表进行两次处理, 导致抛出异常, 在此需要放弃维权处理: 被动的一方(角色)放弃.
修改 Role 封装类:
*** mappedBy 的值为 User 封装类中定义的 Role 的成员变量
@ManyToMany(mappedBy = "roles") //配置多表关系
private Set<User> users = new HashSet();
2. 级联添加(添加用户的同时添加用户对应的角色)
修改 User 封装类:
* 在 User 封装类中的成员属性上修改注解:
(CascadeType.ALL 是级联所有操作)
(CascadeType.MERGE 是级联更新操作)
(CascadeType.PERSIST 是级联保存操作)
(CascadeType.REMOVE 是级联删除操作)
@ManyToMany(targetEntity = Role.class, cascade = CascadeType.ALL)
@JoinTable(name = "sys_user_role", //中间表
//joinColumns, 当前对象在中间表中的外键
joinColumns = {@JoinColumn(name = "sys_user_id", referencedColumnName = "user_id")},
//inverseJoinColumns,对方对象在中间表的外键
inverseJoinColumns = {@JoinColumn(name = "sys_role_id", referencedColumnName = "role_id")}
)
定义级联添加的方法:
@Test
@Transactional
@Rollback(false)
public void testCasCadeAdd() {
//创建一个用户
User user = new User();
user.setUserName("小王");
user.setAge(28);
//用户关联的角色
Role role = new Role();
role.setRoleName("产品经理");
//配置用户到角色关系,可以对中间表中的数据进行维护
user.getRoles().add(role);
//配置角色到用户的关系,可以对中间表的数据进行维护
role.getUsers().add(user);
userDao.save(user);
}
定义级联删除的方法:
@Test
@Transactional
@Rollback(false)
public void testCasCadeRemove() {
//查询1号用户
User user = userDao.findOne(1L);
//删除1号用户
userDao.delete(user);
}