Hibernate多对多操作
多对多映射配置
以用户和角色为例演示
第一步 创建实体类,用户和角色
第二步 让两个实体类之间互相表示
(1)一个用户里面表示所有角色,使用set集合
(2)一个角色有多个用户,使用set集合
第三步 配置映射关系
(1)基本配置
(2)配置多对多关系
在用户里面表示所有角色,使用set标签
在角色里面表示所有用户,使用set标签
两个配置文件直接设置的外键的值需要一致
第四步 在核心配置文件中引入映射文件
代码实践:
user
1 package org.model; 2 3 import java.util.HashSet; 4 import java.util.Set; 5 6 public class User { 7 private Integer u_id; 8 private String u_name; 9 private String u_password; 10 11 //一个用户有多个角色 12 private Set<Role> setrole=new HashSet<Role>(); 13 14 15 public Set<Role> getSetrole() { 16 return setrole; 17 } 18 19 public void setSetrole(Set<Role> setrole) { 20 this.setrole = setrole; 21 } 22 23 public Integer getU_id() { 24 return u_id; 25 } 26 27 public void setU_id(Integer uId) { 28 u_id = uId; 29 } 30 31 public String getU_name() { 32 return u_name; 33 } 34 public void setU_name(String uName) { 35 u_name = uName; 36 } 37 public String getU_password() { 38 return u_password; 39 } 40 public void setU_password(String uPassword) { 41 u_password = uPassword; 42 } 43 }
Role
1 package org.model; 2 3 import java.util.HashSet; 4 import java.util.Set; 5 6 public class Role { 7 private Integer r_id; 8 private String r_name; 9 private String r_memo;//角色介绍 10 11 //一个角色可以有多个用户 12 private Set<User> setuser=new HashSet<User>(); 13 14 15 public Set<User> getSetuser() { 16 return setuser; 17 } 18 public void setSetuser(Set<User> setuser) { 19 this.setuser = setuser; 20 } 21 22 public Integer getR_id() { 23 return r_id; 24 } 25 public void setR_id(Integer rId) { 26 r_id = rId; 27 } 28 public String getR_name() { 29 return r_name; 30 } 31 public void setR_name(String rName) { 32 r_name = rName; 33 } 34 public String getR_memo() { 35 return r_memo; 36 } 37 public void setR_memo(String rMemo) { 38 r_memo = rMemo; 39 } 40 }
User.hbm.xm
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping> 6 <class name="org.model.User" table="t_User"> 7 <id name="u_id" column="u_id"> 8 <generator class="native"></generator> 9 </id> 10 <property name="u_name" column="u_name"></property> 11 <property name="u_password" column="u_password"></property> 12 <!-- name属性 是本配置文件对应的实体类中的set属性值 table属性 是第三张表的名字 --> 13 <set name="setrole" table="user_role"> 14 <!-- column属性 是第三章表中生成的外键的名称 可以随便写 --> 15 <key column="uid"></key> 16 <!-- class属性 是role实体类的全路径 column属性 是第三章表中生成的外键的名称--> 17 <many-to-many class="org.model.Role" column="rid"></many-to-many> 18 </set> 19 </class> 20 </hibernate-mapping>
Role.hbm.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping> 6 <class name="org.model.Role" table="t_Role"> 7 <id name="r_id" column="r_id"> 8 <generator class="native"></generator> 9 </id> 10 <property name="r_name" column="r_name"></property> 11 <property name="r_memo" column="r_memo"></property> 12 <set name="setuser" table="user_role"> 13 <key column="rid"></key> 14 <many-to-many class="org.model.User" column="uid"></many-to-many> 15 </set> 16 </class> 17 </hibernate-mapping>
hibernate.cfg.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-configuration PUBLIC 3 "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> 5 <hibernate-configuration> 6 <session-factory> 7 <!-- 第一步:配置数据库信息 --> 8 <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> 9 <property name="hibernate.connection.username">root</property> 10 <property name="hibernate.connection.password">jay571018</property> 11 <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate3_demo2</property> 12 <!-- 第二步:配置Hibernate信息 --> 13 <property name="hibernate.show_sql">true</property> 14 <property name="hibernate.format_sql">true</property> 15 <!-- 自动建表 --> 16 <property name="hibernate.hbm2ddl.auto">update</property> 17 <!-- 设置数据库方言 --> 18 <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> 19 <!-- 设置与本地线程绑定session --> 20 <property name="hibernate.current_session_context_class">thread</property> 21 22 <!-- 第三步:引入对象关系映射文件 --> 23 <mapping resource="org/model/Role.hbm.xml"/> 24 <mapping resource="org/model/User.hbm.xml"/> 25 </session-factory> 26 </hibernate-configuration>
sessionFactoryutils.java
1 package org.util; 2 3 import org.hibernate.Session; 4 import org.hibernate.SessionFactory; 5 import org.hibernate.cfg.Configuration; 6 7 public class SessionFactoryUtils { 8 static Configuration configuration=null; 9 static SessionFactory sf=null; 10 11 static{ 12 configuration=new Configuration(); 13 configuration.configure();//加载核心配置文件 14 sf=configuration.buildSessionFactory(); 15 } 16 public static Session get(){ 17 return sf.getCurrentSession(); 18 } 19 20 public static void main(String[] args){21 } 22 23 }
执行工具类的代码,然后就会自动建立表
多对多级联保存
根据用户保存角色
第一步 在用户配置文件中set标签进行配置,cascade值save-update
第二步 写代码实现
(1)创建用户和角色对象,把角色放到用户里面,最终保存用户就可以了
1 //演示多对多修级联保存 2 @Test 3 public void testSave() { 4 SessionFactory sessionFactory = null; 5 Session session = null; 6 Transaction tx = null; 7 try { 8 //得到sessionFactory 9 sessionFactory = HibernateUtils.getSessionFactory(); 10 //得到session 11 session = sessionFactory.openSession(); 12 //开启事务 13 tx = session.beginTransaction(); 14 15 //添加两个用户,为每个用户添加两个角色 16 //1 创建对象 17 User user1 = new User(); 18 user1.setUser_name("lucy"); 19 user1.setUser_password("123"); 20 21 User user2 = new User(); 22 user2.setUser_name("mary"); 23 user2.setUser_password("456"); 24 25 Role r1 = new Role(); 26 r1.setRole_name("总经理"); 27 r1.setRole_memo("总经理"); 28 29 Role r2 = new Role(); 30 r2.setRole_name("秘书"); 31 r2.setRole_memo("秘书"); 32 33 Role r3 = new Role(); 34 r3.setRole_name("保安"); 35 r3.setRole_memo("保安"); 36 37 //2 建立关系,把角色放到用户里面 38 // user1 -- r1/r2 39 user1.getSetRole().add(r1); 40 user1.getSetRole().add(r2); 41 42 // user2 -- r2/r3 43 user2.getSetRole().add(r2); 44 user2.getSetRole().add(r3); 45 46 //3 保存用户 47 session.save(user1); 48 session.save(user2); 49 50 //提交事务 51 tx.commit(); 52 53 }catch(Exception e) { 54 tx.rollback(); 55 }finally { 56 session.close(); 57 //sessionFactory不需要关闭 58 sessionFactory.close(); 59 } 60 }
代码实践:
user.hbm.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping> 6 <class name="org.model.User" table="t_User"> 7 <id name="u_id" column="u_id"> 8 <generator class="native"></generator> 9 </id> 10 <property name="u_name" column="u_name"></property> 11 <property name="u_password" column="u_password"></property> 12 <!-- name属性 是本配置文件对应的实体类中的set属性值 table属性 是第三张表的名字 --> 13 <set name="setrole" table="user_role" cascade="save-update"> 14 <!-- column属性 是第三章表中生成的外键的名称 可以随便写 --> 15 <key column="uid"></key> 16 <!-- class属性 是role实体类的全路径 column属性 是第三章表中生成的外键的名称--> 17 <many-to-many class="org.model.Role" column="rid"></many-to-many> 18 </set> 19 </class> 20 </hibernate-mapping>
测试类
1 package org.testdemo; 2 3 import org.hibernate.Session; 4 import org.hibernate.Transaction; 5 import org.junit.Test; 6 import org.model.Role; 7 import org.model.User; 8 import org.util.SessionFactoryUtils; 9 10 public class testDemo { 11 12 /** 13 * @param args 14 */ 15 @Test 16 public void test(){ 17 Session session=null; 18 Transaction tran=null; 19 try{ 20 session=SessionFactoryUtils.get(); 21 //开启事务 22 tran=session.beginTransaction(); 23 //创建两个用户 24 User user1=new User(); 25 User user2=new User(); 26 user1.setU_name("小王"); 27 user1.setU_password("123"); 28 user2.setU_name("小红"); 29 user2.setU_password("456"); 30 //创建3个角色 31 Role role1=new Role(); 32 Role role2=new Role(); 33 Role role3=new Role(); 34 role1.setR_name("总经理"); 35 role1.setR_memo("总经理"); 36 role2.setR_name("秘书"); 37 role2.setR_memo("秘书"); 38 role3.setR_name("清洁工"); 39 role3.setR_memo("清洁工"); 40 41 //建立关系 因为在user配置文件中 set标签内 已经配置了cascade属性 所以 这里只需要保存user就可实现级联保存 42 //否则 还需要在user中添加role role中添加user才能实现功能 这就是级联的优点 43 //假设user1有role1,role2两个角色 44 //假设user2有role2,role3两个角色 45 user1.getSetrole().add(role1); 46 user1.getSetrole().add(role2); 47 user2.getSetrole().add(role2); 48 user2.getSetrole().add(role3); 49 //进行保存 50 session.save(user1); 51 session.save(user2); 52 //提交事务 53 tran.commit(); 54 55 }catch(Exception e){ 56 e.printStackTrace(); 57 }finally{ 58 } 59 } 60 61 }
执行之后的结果:
多对多级联删除(了解)
第一步 在set标签进行配置,cascade值delete
第二步 删除用户
代码实践:
user.hbm.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping> 6 <class name="org.model.User" table="t_User"> 7 <id name="u_id" column="u_id"> 8 <generator class="native"></generator> 9 </id> 10 <property name="u_name" column="u_name"></property> 11 <property name="u_password" column="u_password"></property> 12 <!-- name属性 是本配置文件对应的实体类中的set属性值 table属性 是第三张表的名字 --> 13 <set name="setrole" table="user_role" cascade="save-update,delete"> 14 <!-- column属性 是第三章表中生成的外键的名称 可以随便写 --> 15 <key column="uid"></key> 16 <!-- class属性 是role实体类的全路径 column属性 是第三章表中生成的外键的名称--> 17 <many-to-many class="org.model.Role" column="rid"></many-to-many> 18 </set> 19 </class> 20 </hibernate-mapping>
测试代码:
1 public void testdelete(){ 2 //测试级联删除 3 Session session=null; 4 Transaction tran=null; 5 try{ 6 session=SessionFactoryUtils.get(); 7 //开启事务 8 tran=session.beginTransaction(); 9 10 User user=session.get(User.class,1); 11 session.delete(user); 12 //提交事务 13 tran.commit(); 14 15 }catch(Exception e){ 16 e.printStackTrace(); 17 }finally{ 18 } 19 20 }
执行之后:
可以看到使用级联删除时 有关id为1的对象的数据全部都删除了 所以我们一般不使用级联删除
不使用级联删除测试:
User.hbm.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 <hibernate-mapping> 6 <class name="org.model.User" table="t_User"> 7 <id name="u_id" column="u_id"> 8 <generator class="native"></generator> 9 </id> 10 <property name="u_name" column="u_name"></property> 11 <property name="u_password" column="u_password"></property> 12 <!-- name属性 是本配置文件对应的实体类中的set属性值 table属性 是第三张表的名字 --> 13 <set name="setrole" table="user_role" cascade="save-update"> 14 <!-- column属性 是第三章表中生成的外键的名称 可以随便写 --> 15 <key column="uid"></key> 16 <!-- class属性 是role实体类的全路径 column属性 是第三章表中生成的外键的名称--> 17 <many-to-many class="org.model.Role" column="rid"></many-to-many> 18 </set> 19 </class> 20 </hibernate-mapping>
测试代码不变,执行之后的结果:
只删除了id为1的记录,这个一般是我们需要的删除结果
维护第三张表关系
操作第三张表 就是让某个用户没有某个角色remove 某个用户拥有某个角色add
1 用户和角色多对多关系,维护关系通过第三张表维护
2 让某个用户有某个角色
第一步 根据id查询用户和角色
第二步 把角色放到用户里面
(1)把角色对象放到用户set集合
3 让某个用户没有某个角色
第一步 根据id查询用户和角色
第二步 从用户里面把角色去掉
(1)从set集合里面把角色移除
代码实践:
让1-小王没有 2-总经理这个角色
操作前:
测试代码:
1 @Test 2 public void testremove(){ 3 4 Session session=null; 5 Transaction tran=null; 6 try{ 7 session=SessionFactoryUtils.get(); 8 //开启事务 9 tran=session.beginTransaction(); 10 11 //操作第三张表 就是让某个用户没有某个角色remove 某个用户拥有某个角色add 12 13 //让1-小王没有 2-总经理这个角色 14 //先得到对象的对象 15 User xiaowang=session.get(User.class,1); 16 Role role=session.get(Role.class,2); 17 xiaowang.getSetrole().remove(role); 18 //因为是持久态对象 所以无需保存 提交事务之后 自动会进行表的更新 19 20 21 //提交事务 22 tran.commit(); 23 24 }catch(Exception e){ 25 e.printStackTrace(); 26 }finally{ 27 } 28 }
执行后
让1-小王重新拥有 2-总经理这个角色
操作前
测试代码:
1 @Test 2 public void testadd(){ 3 Session session=null; 4 Transaction tran=null; 5 try{ 6 session=SessionFactoryUtils.get(); 7 //开启事务 8 tran=session.beginTransaction(); 9 10 //操作第三张表 就是让某个用户没有某个角色remove 某个用户拥有某个角色add 11 12 //让1-小王佣有 2-总经理这个角色 13 User xiaowang=session.get(User.class,1); 14 Role role=session.get(Role.class,2); 15 xiaowang.getSetrole().add(role); 16 17 //提交事务 18 tran.commit(); 19 20 }catch(Exception e){ 21 e.printStackTrace(); 22 }finally{ 23 } 24 } 25 }
执行后