首页 > 代码库 > Hibernate多对多操作
Hibernate多对多操作
---------------------siwuxie095
Hibernate 多对多操作
以用户和角色为例
(一)多对多映射配置
第一步:创建两个实体类,用户和角色
第二步:让两个实体类之间互相表示
(1)在用户实体类中表示多个角色
(2)在角色实体类中表示多个用户
第三步:配置映射关系
(1)配置基本的映射
(2)配置关联关系的映射(多对多关系)
1)在用户的映射配置文件中,表示所有角色
2)在角色的映射配置文件中,表示所有用户
第四步:在核心配置文件中引入映射配置文件
(二)多对多级联保存
如:添加两个用户,为每个用户添加两个角色
(1)复杂写法
先在角色的映射配置文件中的 set 标签添加 inverse 属性,并
将其值设置为 true,再进行具体实现
/** * 多对多级联保存的复杂写法 * * * 手动加上 @Test 以进行单元测试(将自动导入 JUnit 4 的 jar 包) * * 选中方法名,右键->Run As->JUint Test */ @Test public void testSave(){
SessionFactory sessionFactory=null; Session session=null; Transaction tx=null;
try { //得到 SessionFactory 对象 sessionFactory=HibernateUtils.getSessionFactory(); //创建 Session 对象 session=sessionFactory.openSession(); //开启事务 tx=session.beginTransaction();
//添加两个用户,为每个用户添加两个角色
//(1) //创建用户和角色对象 User user1=new User(); user1.setUserName("小白"); user1.setUserPassword("8888");
User user2=new User(); user2.setUserName("小黑"); user2.setUserPassword("4444");
Role role1=new Role(); role1.setRoleName("保镖"); role1.setRoleMemo("强大的保镖");
Role role2=new Role(); role2.setRoleName("秘书"); role2.setRoleMemo("漂亮的秘书");
Role role3=new Role(); role3.setRoleName("司机"); role3.setRoleMemo("称职的司机");
//(2) //建立用户和角色对象的关系 // //在用户实体类中表示角色,在角色实体类中表示用户 // //具体: //把角色对象放到用户对象的 Set 集合中 //把用户对象放到角色对象的 Set 集合中 // //user1 --- role1 / role2 //user2 --- role1 / role3 // //注意:如果建立了双向的关系,一定要有一方放弃外 //键维护权。如下 user1.getRoleSet().add(role1); user1.getRoleSet().add(role2); user2.getRoleSet().add(role1); user2.getRoleSet().add(role3);
role1.getUserSet().add(user1); role1.getUserSet().add(user2); role2.getUserSet().add(user1); role3.getUserSet().add(user2);
//(3)保存到数据库(级联保存) session.save(user1); session.save(user2); session.save(role1); session.save(role2); session.save(role3);
/* * 由于是多对多且进行了双向关联,所以一定要有一方 * 放弃外键维护权,否则将无法保存到数据库中 * * 一般由被动方放弃外键维护权,这里角色是被动方 * * 具体做法: * * 在角色的映射配置文件中的 set 标签中添加 inverse * 属性,并将其值设置为 true */
//提交事务 tx.commit(); } catch (Exception e) { //回滚事务 tx.rollback(); } finally { //关闭资源 session.close(); sessionFactory.close(); } } |
(2)简化写法
先在用户的映射配置文件中的 set 标签添加 cascade 属性,并
将其值设置为 save-update,再进行具体实现
/** * 多对多级联保存的简化写法 * * 在用户的映射配置文件中的 set 标签 * 添加 cascade 属性,并将其值设置为 * save-update */ @Test public void testSaveX(){
SessionFactory sessionFactory=null; Session session=null; Transaction tx=null;
try { //得到 SessionFactory 对象 sessionFactory=HibernateUtils.getSessionFactory(); //创建 Session 对象 session=sessionFactory.openSession(); //开启事务 tx=session.beginTransaction();
//添加两个用户,为每个用户添加两个角色
//(1) //创建用户和角色对象 User user1=new User(); user1.setUserName("小白"); user1.setUserPassword("8888");
User user2=new User(); user2.setUserName("小黑"); user2.setUserPassword("4444");
Role role1=new Role(); role1.setRoleName("保镖"); role1.setRoleMemo("强大的保镖");
Role role2=new Role(); role2.setRoleName("秘书"); role2.setRoleMemo("漂亮的秘书");
Role role3=new Role(); role3.setRoleName("司机"); role3.setRoleMemo("称职的司机");
//(2) //建立用户和角色对象的关系 // //在用户实体类中表示角色 // //具体: //把角色对象放到用户对象的 Set 集合中 // //user1 --- role1 / role2 //user2 --- role1 / role3 user1.getRoleSet().add(role1); user1.getRoleSet().add(role2); user2.getRoleSet().add(role1); user2.getRoleSet().add(role3);
//(3)保存到数据库(级联保存) session.save(user1); session.save(user2);
//提交事务 tx.commit(); } catch (Exception e) { //回滚事务 tx.rollback(); } finally { //关闭资源 session.close(); sessionFactory.close(); } } |
(三)多对多级联删除(一般不使用,仅作了解)
如:删除某个用户
先在用户的映射配置文件中的 set 标签添加 cascade 属性,并
将其值设置为 delete,再进行具体实现
/** * 多对多级联删除 * * 简化写法:在用户的映射配置文件中的 set 标签 * 添加 cascade 属性,并将其值设置为 delete */ @Test public void testDelete(){
SessionFactory sessionFactory=null; Session session=null; Transaction tx=null;
try { //得到 SessionFactory 对象 sessionFactory=HibernateUtils.getSessionFactory(); //创建 Session 对象 session=sessionFactory.openSession(); //开启事务 tx=session.beginTransaction();
//(1) //通过 id 查询用户对象 User user=session.get(User.class, 1);
//(2) //调用 Session 的 delete() 方法实现级联删除 session.delete(user);
//多对多级联删除,一般不使用,仅作了解即可 // //注意:此时角色的映射配置文件中的 set 标签 //不能将 inverse 属性设为 true,否则将无法 //删除 // //另外:set 标签也不能将 cascade 属性设为 //delete,否则 testSaveX() 方法保存的数据 //将全部删除
//提交事务 tx.commit(); } catch (Exception e) { //回滚事务 tx.rollback(); } finally { //关闭资源 session.close(); sessionFactory.close(); } } |
(四)维护第三张表
通过第三张表来维护多对多关系
如:让某个用户有某个角色
第一步:根据 id 查询用户和角色
第二步:把角色对象放到用户对象的 Set 集合中
再如:让某个用户没有某个角色
第一步:根据 id 查询用户和角色
第二步:从用户对象的 Set 集合中移除角色对象
/** * 维护第三张表 */ @Test public void testTable(){
SessionFactory sessionFactory=null; Session session=null; Transaction tx=null;
try { //得到 SessionFactory 对象 sessionFactory=HibernateUtils.getSessionFactory(); //创建 Session 对象 session=sessionFactory.openSession(); //开启事务 tx=session.beginTransaction();
//让某个用户有某个角色
//(1)根据 id 查询用户对象和角色对象 User user=session.get(User.class, 1); Role role=session.get(Role.class, 3);
//(2)把角色对象放到用户对象的 Set 集合中 user.getRoleSet().add(role);
//让某个用户没有某个角色
//(1)根据 id 查询用户对象和角色对象 User userx=session.get(User.class, 1); Role rolex=session.get(Role.class, 1);
//(2)从用户对象的 Set 集合中移除角色对象 userx.getRoleSet().remove(rolex);
//提交事务 tx.commit(); } catch (Exception e) { //回滚事务 tx.rollback(); } finally { //关闭资源 session.close(); sessionFactory.close(); } } |
工程结构目录如下:
HibernateUtils.java:
package com.siwuxie095.utils;
import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration;
public class HibernateUtils {
static Configuration cfg=null; static SessionFactory sessionFactory=null;
//或: 加上 private final 亦可,不过此时不能等于 null // private static final Configuration cfg; // private static final SessionFactory sessionFactory;
//静态代码块 static { //加载核心配置文件 cfg=new Configuration(); cfg.configure(); sessionFactory=cfg.buildSessionFactory();
}
//提供方法返回 sessionFactory public static SessionFactory getSessionFactory() { return sessionFactory; }
//提供方法返回与本地线程绑定的 Session public static Session getCurrentSession() { return sessionFactory.getCurrentSession(); }
} |
User.java:
package com.siwuxie095.entity;
import java.util.HashSet; import java.util.Set;
//用户实体类 public class User {
private Integer uid; //用户 id private String userName; //用户名称 private String userPassword; //用户密码
//在用户实体类中表示多个角色,即 一个用户可以有多个角色 // //Hibernate 中要求使用 Set 集合表示"多"的数据 private Set<Role> roleSet=new HashSet<Role>();
public Set<Role> getRoleSet() { return roleSet; } public void setRoleSet(Set<Role> roleSet) { this.roleSet = roleSet; }
public Integer getUid() { return uid; } public void setUid(Integer uid) { this.uid = uid; }
public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; }
public String getUserPassword() { return userPassword; } public void setUserPassword(String userPassword) { this.userPassword = userPassword; }
} |
Role.java:
package com.siwuxie095.entity;
import java.util.HashSet; import java.util.Set;
//角色实体类 public class Role {
private Integer rid; //角色 id private String roleName; //角色名称 private String roleMemo; //角色描述
//在角色实体类中表示多个用户,即 一个角色可以有多个用户 // //Hibernate 中要求使用 Set 集合表示"多"的数据 private Set<User> userSet=new HashSet<User>();
public Set<User> getUserSet() { return userSet; } public void setUserSet(Set<User> userSet) { this.userSet = userSet; }
public Integer getRid() { return rid; } public void setRid(Integer rid) { this.rid = rid; }
public String getRoleName() { return roleName; } public void setRoleName(String roleName) { this.roleName = roleName; }
public String getRoleMemo() { return roleMemo; } public void setRoleMemo(String roleMemo) { this.roleMemo = roleMemo; }
} |
HibernateManyToMany.java:
package com.siwuxie095.hibernatetest;
import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.junit.Test;
import com.siwuxie095.entity.Role; import com.siwuxie095.entity.User; import com.siwuxie095.utils.HibernateUtils;
//多对多操作 public class HibernateManyToMany {
/** * 多对多级联保存的复杂写法 * * * 手动加上 @Test 以进行单元测试(将自动导入 JUnit 4 的 jar 包) * * 选中方法名,右键->Run As->JUint Test */ @Test public void testSave(){
SessionFactory sessionFactory=null; Session session=null; Transaction tx=null;
try { //得到 SessionFactory 对象 sessionFactory=HibernateUtils.getSessionFactory(); //创建 Session 对象 session=sessionFactory.openSession(); //开启事务 tx=session.beginTransaction();
//添加两个用户,为每个用户添加两个角色
//(1) //创建用户和角色对象 User user1=new User(); user1.setUserName("小白"); user1.setUserPassword("8888");
User user2=new User(); user2.setUserName("小黑"); user2.setUserPassword("4444");
Role role1=new Role(); role1.setRoleName("保镖"); role1.setRoleMemo("强大的保镖");
Role role2=new Role(); role2.setRoleName("秘书"); role2.setRoleMemo("漂亮的秘书");
Role role3=new Role(); role3.setRoleName("司机"); role3.setRoleMemo("称职的司机");
//(2) //建立用户和角色对象的关系 // //在用户实体类中表示角色,在角色实体类中表示用户 // //具体: //把角色对象放到用户对象的 Set 集合中 //把用户对象放到角色对象的 Set 集合中 // //user1 --- role1 / role2 //user2 --- role1 / role3 // //注意:如果建立了双向的关系,一定要有一方放弃外 //键维护权。如下 user1.getRoleSet().add(role1); user1.getRoleSet().add(role2); user2.getRoleSet().add(role1); user2.getRoleSet().add(role3);
role1.getUserSet().add(user1); role1.getUserSet().add(user2); role2.getUserSet().add(user1); role3.getUserSet().add(user2);
//(3)保存到数据库(级联保存) session.save(user1); session.save(user2); session.save(role1); session.save(role2); session.save(role3);
/* * 由于是多对多且进行了双向关联,所以一定要有一方 * 放弃外键维护权,否则将无法保存到数据库中 * * 一般由被动方放弃外键维护权,这里角色是被动方 * * 具体做法: * * 在角色的映射配置文件中的 set 标签中添加 inverse * 属性,并将其值设置为 true */
//提交事务 tx.commit(); } catch (Exception e) { //回滚事务 tx.rollback(); } finally { //关闭资源 session.close(); sessionFactory.close(); } }
/** * 多对多级联保存的简化写法 * * 在用户的映射配置文件中的 set 标签 * 添加 cascade 属性,并将其值设置为 * save-update */ @Test public void testSaveX(){
SessionFactory sessionFactory=null; Session session=null; Transaction tx=null;
try { //得到 SessionFactory 对象 sessionFactory=HibernateUtils.getSessionFactory(); //创建 Session 对象 session=sessionFactory.openSession(); //开启事务 tx=session.beginTransaction();
//添加两个用户,为每个用户添加两个角色
//(1) //创建用户和角色对象 User user1=new User(); user1.setUserName("小白"); user1.setUserPassword("8888");
User user2=new User(); user2.setUserName("小黑"); user2.setUserPassword("4444");
Role role1=new Role(); role1.setRoleName("保镖"); role1.setRoleMemo("强大的保镖");
Role role2=new Role(); role2.setRoleName("秘书"); role2.setRoleMemo("漂亮的秘书");
Role role3=new Role(); role3.setRoleName("司机"); role3.setRoleMemo("称职的司机");
//(2) //建立用户和角色对象的关系 // //在用户实体类中表示角色 // //具体: //把角色对象放到用户对象的 Set 集合中 // //user1 --- role1 / role2 //user2 --- role1 / role3 user1.getRoleSet().add(role1); user1.getRoleSet().add(role2); user2.getRoleSet().add(role1); user2.getRoleSet().add(role3);
//(3)保存到数据库(级联保存) session.save(user1); session.save(user2);
//提交事务 tx.commit(); } catch (Exception e) { //回滚事务 tx.rollback(); } finally { //关闭资源 session.close(); sessionFactory.close(); } }
/** * 多对多级联删除 * * 简化写法:在用户的映射配置文件中的 set 标签 * 添加 cascade 属性,并将其值设置为 delete */ @Test public void testDelete(){
SessionFactory sessionFactory=null; Session session=null; Transaction tx=null;
try { //得到 SessionFactory 对象 sessionFactory=HibernateUtils.getSessionFactory(); //创建 Session 对象 session=sessionFactory.openSession(); //开启事务 tx=session.beginTransaction();
//(1) //通过 id 查询用户对象 User user=session.get(User.class, 1);
//(2) //调用 Session 的 delete() 方法实现级联删除 session.delete(user);
//多对多级联删除,一般不使用,仅作了解即可 // //注意:此时角色的映射配置文件中的 set 标签 //不能将 inverse 属性设为 true,否则将无法 //删除 // //另外:set 标签也不能将 cascade 属性设为 //delete,否则 testSaveX() 方法保存的数据 //将全部删除
//提交事务 tx.commit(); } catch (Exception e) { //回滚事务 tx.rollback(); } finally { //关闭资源 session.close(); sessionFactory.close(); } }
/** * 维护第三张表 */ @Test public void testTable(){
SessionFactory sessionFactory=null; Session session=null; Transaction tx=null;
try { //得到 SessionFactory 对象 sessionFactory=HibernateUtils.getSessionFactory(); //创建 Session 对象 session=sessionFactory.openSession(); //开启事务 tx=session.beginTransaction();
//让某个用户有某个角色
//(1)根据 id 查询用户对象和角色对象 User user=session.get(User.class, 1); Role role=session.get(Role.class, 3);
//(2)把角色对象放到用户对象的 Set 集合中 user.getRoleSet().add(role);
//让某个用户没有某个角色
//(1)根据 id 查询用户对象和角色对象 User userx=session.get(User.class, 1); Role rolex=session.get(Role.class, 1);
//(2)从用户对象的 Set 集合中移除角色对象 userx.getRoleSet().remove(rolex);
//提交事务 tx.commit(); } catch (Exception e) { //回滚事务 tx.rollback(); } finally { //关闭资源 session.close(); sessionFactory.close(); } } } |
User.hbm.xml:
<?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>
<!-- (1) class 标签:配置实体类和数据库表的对应; name 属性:实体类的全路径,即 全限定名; table 属性:数据库表的名称(数据库表由 Hibernate 自动生成) --> <class name="com.siwuxie095.entity.User" table="t_user">
<!-- (2) id 标签:配置实体类 id 和表 id 对应(主键); name 属性:实体类里 id 属性名称; column 属性:生成表中 id 字段名称 --> <id name="uid" column="uid"> <generator class="native"></generator> </id>
<!-- (3) property 标签:配置其它属性和表中字段对应; name 属性:实体类属性名称; column 属性:生成表中字段名称 --> <property name="userName" column="user_name"></property> <property name="userPassword" column="user_password"></property>
<!-- (4) set 标签:配置关联关系的映射(配置关联对象),代表一个 Set 集合; name 属性:关联另一方的对象的 Set 集合的名称(在用户实体类中声明); table 属性:第三张表的名称; cascade 属性:save-update 表示级联保存,delete 表示级联删除(逗号隔开); inverse 属性:true 表示放弃关系维护(放弃外键的维护权)(默认为 false) -->
<set name="roleSet" table="user_role" cascade="delete">
<!-- key 标签:配置当前对象(关联一方)在第三张表中的外键 column 属性:当前对象(关联一方)在第三张表中的外键名称 --> <key column="user_id"></key>
<!-- many-to-many 标签:配置实体类的多对多关联; class:关联另一方的类的全路径,即 角色实体类的全限定名; column:关联的另一方在第三张表的外键名称,即 角色表在第三张表中的外键名称 --> <many-to-many class="com.siwuxie095.entity.Role" column="role_id"></many-to-many> </set> </class> </hibernate-mapping> |
Role.hbm.xml:
<?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>
<class name="com.siwuxie095.entity.Role" table="t_role">
<id name="rid" column="rid"> <generator class="native"></generator> </id>
<property name="roleName" column="role_name"></property> <property name="roleMemo" column="role_memo"></property>
<!-- set 标签:配置关联关系的映射(配置关联对象),代表一个 Set 集合; name 属性:关联另一方的对象的 Set 集合的名称(在角色实体类中声明); table 属性:第三张表的名称; cascade 属性:save-update 表示级联保存,delete 表示级联删除(逗号隔开); inverse 属性:true 表示放弃关系维护(放弃外键的维护权)(默认为 false) --> <set name="userSet" table="user_role" cascade="save-update" inverse="false">
<!-- key 标签:配置当前对象(关联一方)在第三张表中的外键 column 属性:当前对象(关联一方)在第三张表中的外键名称 --> <key column="role_id"></key>
<!-- many-to-many 标签:配置实体类的多对多关联; class:关联另一方的类的全路径,即 用户实体类的全限定名; column:关联的另一方在第三张表的外键名称,即 用户表在第三张表中的外键名称 --> <many-to-many class="com.siwuxie095.entity.User" column="user_id"></many-to-many> </set> </class> </hibernate-mapping> |
hibernate.cfg.xml:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory>
<!-- 第一部分:配置数据库信息(必须) -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <!-- 或使用 jdbc:mysql:///hibernate_db 代替,省略 localhost:3306 --> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate_db</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">8888</property>
<!-- 第二部分:配置 Hibernate 信息(可选) -->
<!-- 输出底层 sql 语句 --> <property name="hibernate.show_sql">true</property> <!-- 输出底层 sql 语句格式 --> <property name="hibernate.format_sql">true</property> <!-- Hibernate 帮助创建表,不是自动创建,而需要配置之后。 update:如果已经有表,就更新,如果没有,就自动创建 --> <property name="hibernate.hbm2ddl.auto">update</property> <!-- 配置数据库方言,让 Hibernate 框架识别不同数据库自己特有的语句 如:在 MySQL 中实现分页的关键字 limit,只能在 MySQL 中使用,而 在 Oracle 中实现分页的关键字则是 rownum --> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <!-- 配置 Session 绑定本地线程 --> <property name="hibernate.current_session_context_class">thread</property>
<!-- 第三部分:引入映射配置文件,把映射配置文件放到核心配置文件(必须) -->
<mapping resource="com/siwuxie095/entity/User.hbm.xml"/> <mapping resource="com/siwuxie095/entity/Role.hbm.xml"/>
</session-factory> </hibernate-configuration> |
【made by siwuxie095】
Hibernate多对多操作