需求:用户与角色是多对多的关系
一、模型设计
1、设计表(用hibernate自动生成表)
用户表
角色表
用户角色表
2、创建User实体类
package com.**.hibernate.pojo.many2many;
import java.util.HashSet;
import java.util.Set;
/**
* 用户(多方)
*/
public class User{
private Integer id;
private String name;
//关联角色
private Set<Role> roles = new HashSet<Role>();
} |
注:一般在开发中配置多方时用的都是set集合,在Mapping配置文件时,配置节点为<set>,
因为List允许重复的值,所以一般不用,感兴趣的可以自己实验一下,只需要把Mapping配置文件中
把<set>节点变成<list>节点即可(标签内的子标签有差别,注意不要直接把set变成list)
3、创建Role实体类
package com.**.hibernate.pojo.many2many;
import
java.util.HashSet;
import java.util.Set;
/**
* 角色(多方)
*/
public class Role{
private Integer id;
private String name;
//关联用户
private Set<User> users = new HashSet<User>();} |
4、User配置
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.**.hibernate.pojo.many2many">
<class name="User" table="t_user">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="name" column="name"></property>
<!-- 多对多映射 -->
<!--
table:中间表名
-->
<set name="roles" table="t_user_role">
<!-- 当前方在中间表的外键 -->
<key column="user_id"/>
<!-- column:对方在中间表的外键 -->
<many-to-many class="Role" column="role_id"/>
</set>
</class>
</hibernate-mapping>
|
5、Role配置
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.**.hibernate.pojo.many2many">
<class name="Role" table="t_role">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="name" column="name"></property>
<!-- 多对多映射 -->
<!--
table:中间表名
-->
<set name="users" table="t_user_role">
<!-- 当前方在中间表的外键 -->
<key column="role_id"/>
<!-- column:对方在中间表的外键 -->
<many-to-many class="User" column="user_id"/>
</set>
</class>
</hibernate-mapping>
|
6、将映射文件加入hibernte.cfg.xml
<mapping resource="com/**/hibernate/pojo/many2many/User.hbm.xml"/>
<mapping resource="com/**/hibernate/pojo/many2many/Role.hbm.xml"/> |
二、测试增加
1、inverse
注意:如果不设置 inverse选项,那么执行以下测试会报告错误: Duplicate entry '1-1' for key 'PRIMARY'
查看控制台发现,多出一条sql语句:
insert
into
t_user_role ...
因为User 和 Role 都同时维护了 中间表,导致插入数据联合主键重复,
因此可以在Role配置文件的 set 节点中设置 inverse="true"
<set name="users" table="t_user_role" inverse="true"> |
public class
Many2ManyTest {
/** * 需求:建立1个用户,1个角色 */ @Test public void testCreateUserAndRole(){ User user = new User(); user.setName("奥特曼"); Role role = new Role(); role.setName("超级管理员"); //建立双向关系 user.getRoles().add(role); role.getUsers().add(user); Session session = HibernateUtil.openSession(); Transaction tx = session.beginTransaction(); session.save(user); session.save(role); tx.commit(); session.close(); } } |
三、级联保存
1、在User配置文件中配置级联保存
<set name="roles" table="t_user_role" cascade="save-update"> |
2、建立双项关联,只保存user
在设置了inverse的情况下,必须建立双向关联,否则关系表中的数据无法添加
//建立双向关系 user.getRoles().add(role); role.getUsers().add(user); Session session = HibernateUtil.openSession(); Transaction tx = session.beginTransaction(); session.save(user); //session.save(role); |
四、级联删除
(1)
如果
不设置级联删除,则只删除用户记录和关联表记录,不会删除角色记录
/**
* 级联删除操作
*/
@Test
public void testCascadeDelete(){
Session session = HibernateUtil.openSession();
Transaction tx = session.beginTransaction();
User u = session.get(User.class, 3);
session.delete(u);
tx.commit();
session.close();
} |
(2)
如果设置级联删除,除了删除
用户记录和关联表记录,还会删除角色记录!
在实际开发中,在多对多的关系中不要使用级联删除!!!
<set name="roles" table="t_user_role" cascade="save-update,delete"> |