06-Hibernate中一对多,多对一,多对多分别在数据库表,对象entity,以及xml文件中的表达

06-Hibernate中一对多,多对一,多对多分别在数据库表,对象entity,以及xml文件中的表达

  • 一对多|多对一

    • 关系表达
      • 表中的表达

        • 在表中的表达,例如客户对联系人,客户是一的一方,联系人是多的一方,也就是一个客户下可以有多个联系人,而多个联系人对应一个客户,所以客户对联系人就是一对多的关系,联系人对客户就是多对一的关系,数据库表中在多的一方使用外键表示关联关系。(详情请参考图片)
          在这里插入图片描述
      • 实体中的表达

        • 在实体中的表达,例如客户对联系人,在一的一方创建私有的联系人set集合并new出来(new出来的作用就是方便后面传参),在多的一方创建私有的客户对象。(详情请参考图片)
          在这里插入图片描述
      • 对象关系映射配置文件中的表达

        • 在xxx.hbm.xml配置文件中,例如客户对联系人,在(客户)方创建一个set标签,name属性为实体文件中创建的set集合,inverse属性为性能优化,提高关系维护的性能,cascade属性为级联操作,简化操作,省代码;set标签下的key标签,column属性为外键列名;set标签下的one-to-many标签,class属性为关联的对象的完整类名

          <!-- 集合,一对多关系,在配置文件中配置 -->
              		<!-- 
              			name属性:集合属性
              			column属性:外键列名
              			class属性:填写与我关联的对象完整类名
              		 -->
              		 <!-- 
              		 	级联操作:cascade
              		 	 save-update:级联保存更新
              		 	 delete:级联删除。
              		 	 all:save-update+delete
              		 级联操作:简化操作.目的就是少写2行代码而已。
              		  -->
              		  <!-- inverse属性:配置关系是否维护。
              		  		true:当前配置的customer是不维护关系,
              		  		false(默认值):customer维护关系
              		  		
              		  		inverse属性:性能优化,提高关系维护的性能。
              		  		原则:无论怎么放弃,总有一个必须要维护,
              		  		一对多关系中:一的一方放弃,也只能一的一方放弃,多的一方不能放弃的。
              		   -->
              		<set name="linkMens" inverse="true" cascade="delete">
              			<key column="lkm_cust_id"></key>
              			<one-to-many class="LinkMan"/>
              		</set>
          
        • 在xxx.hbm.xml配置文件中,例如客户对联系人,在(联系人)方创建一个many-to-one标签,name属性就是创建的客户对象名称,column属性是外键列名,class属性与我关联的对象的完整类名(客户)。

          <!-- 多对一 -->
              		<!-- 
              			name属性:引用属性名
              			column属性:外键列名
              			class属性:与我关联的对象完整类名
              		
              		 -->
              		  <!-- 
              		 	级联操作:cascade
              		 	 save-update:级联保存更新
              		 	 delete:级联删除。
              		 	 all:save-update+delete
              		 级联操作:简化操作.目的就是少写2行代码而已。
              		  -->
              		  <!-- 多的一方:不能放弃维护关系的,外键字段就在多的一方。 -->
              			<many-to-one name="customer" column="lkm_cust_id" class="Customer" ></many-to-one>
          
      • 一对多,多对一在实际中的操作

        @Test
        	//保存客户,以及客户下的联系人
        	public void fun1(){
        		//1.获得session
        		Session session = HibernateUtils.openSession();
        		//2.开启事务
        		Transaction tx = session.beginTransaction();
        		//----------------------------------------------
        		//3.操作
        			Customer c = new Customer();
        			c.setCust_name("潭州教育");
        			
        			LinkMan lm1 = new LinkMan();
        			lm1.setLkm_name("清子");
        			LinkMan lm2 = new LinkMan();
        			lm2.setLkm_name("好人");
        			
        			//开始表达关系
        			//一对多,客户下有2个联系人,清子和好人
        			c.getLinkMans().add(lm1);
        			c.getLinkMans().add(lm2);
        			
        			//多对一,练习人属于哪个客户
        			lm1.setCustomer(c);
        			lm2.setCustomer(c);
        			
        			//执行保存操作,将瞬时状态的对象转化为持久化状态
        			session.save(c);
        			session.save(lm1);
        			session.save(lm2);
        		
        		//----------------------------------------------
        		//4.提交事务
        		tx.commit();
        		//5.关闭资源
        		session.close();
        	}
        
        @Test
        	//为客户添加联系人
        	public void fun2(){
        		//1.获得session
        		Session session = HibernateUtils.openSession();
        		//2.开启事务
        		Transaction tx = session.beginTransaction();
        		//----------------------------------------------
        		//3.操作
        			//1.获得要操作的客户对象
        			Customer c = session.get(Customer.class, 1L);
        			//2.创建联系人
        			LinkMan lm1 = new LinkMan();
        			lm1.setLkm_name("金千亿");
        			
        			//3.将联系人添加到客户,将客户设置到联系人中
        			c.getLinkMans().add(lm1);
        			lm1.setCustomer(c);
        			//4.执行保存
        			session.save(lm1);
        		//----------------------------------------------
        		//4.提交事务
        		tx.commit();
        		//5.关闭资源
        		session.close();
        	}
        
        @Test
        	//为客户删除联系人
        	public void fun3(){
        		//1.获得session
        		Session session = HibernateUtils.openSession();
        		//2.开启事务
        		Transaction tx = session.beginTransaction();
        		//----------------------------------------------
        		//3.操作
        			//1.获取要操作的对象
        			Customer c = session.get(Customer.class, 1l);
        			//2.获得要移除的联系人
        			LinkMan lm1 = session.get(LinkMan.class, 1l);
        			//3.将联系人从客户集合中删除
        			c.getLinkMans().remove(lm1);
        			lm1.setCustomer(null);
        		//----------------------------------------------
        		//4.提交事务
        		tx.commit();
        		//5.关闭资源
        		session.close();
        	}
        
      • 测试级联保存

        @Test
        	//保存客户,以及客户下的联系人
        	//cascade:save-update
        	public void fun1(){
        		//1.获得session
        		Session session = HibernateUtils.openSession();
        		//2.开启事务
        		Transaction tx = session.beginTransaction();
        		//----------------------------------------------
        		//3.操作
        			Customer c = new Customer();
        			c.setCust_name("潭州教育");
        			
        			LinkMan lm1 = new LinkMan();
        			lm1.setLkm_name("清子");
        			LinkMan lm2 = new LinkMan();
        			lm2.setLkm_name("好人");
        			
        			//开始表达关系
        			//一对多,客户下有2个联系人,清子和好人
        			c.getLinkMans().add(lm1);
        			c.getLinkMans().add(lm2);
        			
        			//多对一,练习人属于哪个客户
        			lm1.setCustomer(c);
        			lm2.setCustomer(c);
        			
        			//执行保存操作,将瞬时状态的对象转化为持久化状态
        			session.save(c);
        			//使用了级联保存,这里就可以不用保存后面两条了
        			//session.save(lm1);
        			//session.save(lm2);
        		
        		//----------------------------------------------
        		//4.提交事务
        		tx.commit();
        		//5.关闭资源
        		session.close();
        	}
        
        @Test
        	//测试删除客户时,级联删除(解除)客户下的联系人
        	//cascade:delete
        	public void fun2(){
        		//1.获得session
        		Session session = HibernateUtils.openSession();
        		//2.开启事务
        		Transaction tx = session.beginTransaction();
        		//----------------------------------------------
        		//3.操作
        			//1.获取要操作的对象
        			Customer c = session.get(Customer.class, 1l);
        			//2.调用delete删除(接触)客户
        			session.delete(c);
        			
        		//----------------------------------------------
        		//4.提交事务
        		tx.commit();
        		//5.关闭资源
        		session.close();
        	}
        
        @Test
        	//保存联系人以及联系人对应的客户
        	//cascade:save-update
        	public void fun3(){
        		//1.获得session
        		Session session = HibernateUtils.openSession();
        		//2.开启事务
        		Transaction tx = session.beginTransaction();
        		//----------------------------------------------
        		//3.操作
        			Customer c = new Customer();
        			c.setCust_name("tz");
        			
        			LinkMan lm1 = new LinkMan();
        			lm1.setLkm_name("老二");
        			
        			//一对多,客户下有多个联系人
        			c.getLinkMans().add(lm1);
        			
        			//表达多对一,联系人属于哪个客户
        			lm1.setCustomer(c);
        			
        			//这里要保存一的一方,不能保存多的一方,否则报错,这里是报错的
        			session.save(lm1);
        			
        		//----------------------------------------------
        		//4.提交事务
        		tx.commit();
        		//5.关闭资源
        		session.close();
        	}
        
      • 操作进阶–关系维护属性

        @Test
        	//保存客户,以及客户下的联系人
        	//cascade:save-update
        	public void fun1(){
        		//1.获得session
        		Session session = HibernateUtils.openSession();
        		//2.开启事务
        		Transaction tx = session.beginTransaction();
        		//----------------------------------------------
        		//3.操作
        			Customer c = new Customer();
        			c.setCust_name("哈哈哈哈");
        			
        			LinkMan lm1 = new LinkMan();
        			lm1.setLkm_name("清子");
        			LinkMan lm2 = new LinkMan();
        			lm2.setLkm_name("好人");
        			
        			//一对多,客户下有多个联系人
        			//如果咱们的客户放弃维护与联系人的关系,维护关系的代码可以省略
        			//c.getLinkMans().add(lm1);
        			//c.getLinkMans().add(lm2);
        			
        			//多对一,联系人属于哪个客户
        			lm1.setCustomer(c);
        			lm2.setCustomer(c);
        			
        			//执行保存操作,将瞬时状态的对象转化为持久化状态
        			session.save(c);
        			session.save(lm1);
        			session.save(lm2);
        		
        		//----------------------------------------------
        		//4.提交事务
        		tx.commit();
        		//5.关闭资源
        		session.close();
        	}
        
        @Test
        	//为客户删除联系人
        	//cascade:save-update
        	public void fun2(){
        		//1.获得session
        		Session session = HibernateUtils.openSession();
        		//2.开启事务
        		Transaction tx = session.beginTransaction();
        		//----------------------------------------------
        		//3.操作---当cascade:save-update,如果客户放弃维护关系的话,在删除的时候,就无法通过删除客户来删除数据了
        			Customer c = session.get(Customer.class, 1l);
        			session.delete(c);
        			
        		//----------------------------------------------
        		//4.提交事务
        		tx.commit();
        		//5.关闭资源
        		session.close();
        	}
        
  • 多对多

    • 关系表达

      • 在表中的表达,例如员工表和角色表中,一个员工在公司可以有多种角色,一个角色也可以由多名员工承担,所以员工表和角色表是多对多的关系,在数据库表中,使用第三张表(中间表)来表示,中间表至少有两列,都是外键分别引用,两张表的主键关系。如图所示
        在这里插入图片描述

      • 在实体中的表达,例如员工与角色对象,分别在双方的实体中声明私有的对方set集合属性,在员工对象中创建private Set<角色> roles; 在角色表中创建private Set<员工> users; 这样两方都能使用集合来表达拥有多个对方。如图所示
        在这里插入图片描述

      • 在对象关系映射配置文件中表达

        • 在员工关系映射配置文件中

          <!-- 多对多关系表达 -->
              		<!-- 
              			name属性:集合属性名
              			table:配置中间表名
              			key
              				column:外键,别人引用我的外键列名
              				Class:我与那个类是多对多关系
              				column:外键,我引用别人的外键列名
              		 -->
              		 <!-- cascade级联操作:
              		 		save-update: 级联保存更新
              		 		delete: 级联删除
              		 		all:级联保存更新+级联删除
              		 	结论:cascade简化代码书写。该属性使不使用无所谓,建议要用只用save-update
              		 	     如果使用delete操作太过危险。尤其是在多对多中,不建议使用。
              		  -->
              		 <set name="roles" table="sys_user_role" cascade="save-update">
              		 	<key column="user_id"></key>
              		 	<many-to-many class="Role" column="role_id"></many-to-many>
              		 </set>
          
        • 在角色关系配置文件中

          <!-- 使用inverse属性
          	    		true:放弃维护外键关系
          	    		false(默认值):维护关系
          	    		
          	    		结论:将来在开发中,如果遇到多对多关系,一定要选择一方放弃维护关系。
          	    		一般谁来放弃要看业务方向。列如:录入员工时,需要为员工指定所属角色。
          	    		那么业务方向就是由员工维护角色。角色不需要维护与员工的关系。所以角色放弃维护。
              	 	-->
              		<set name="users" table="sys_user_role" inverse="true">
              			<key column="role_id"></key>
              			<many-to-many class="User" column="user_id"></many-to-many>
              		</set>
          
      • 多对多关系在实际中的应用

        @Test
        	//保存员工以及角色
        	public void fun1(){
        		//1、获得session
        		Session session = HibernateUtils.openSession();
        		//2、开启事务
        		Transaction tx = session.beginTransaction();
        		//---------------------------------------------
        		//3.操作
        			//1.创建两个USER
        			User u1 = new User();
        			u1.setUser_name("大明星");
        			User u2 = new User();
        			u2.setUser_name("清子");
        			
        			//2。创建两Role
        			Role r1 = new Role();
        			r1.setRole_name("保洁");
        			Role r2 = new Role();
        			r2.setRole_name("前台");
        			
        			//3.用户表达关系
        			u1.getRoles().add(r1);
        			u1.getRoles().add(r2);
        			
        			u2.getRoles().add(r1);
        			u2.getRoles().add(r2);
        			
        			//4.角色表达
        			r1.getUsers().add(u1);
        			r1.getUsers().add(u2);
        			
        			r2.getUsers().add(u1);
        			r2.getUsers().add(u2);
        			
        			//5.调用save方法一次保存
        			session.save(u1);
        			session.save(u2);
        			session.save(r1);
        			session.save(r2);
        			
        		//-------------------------------------------
        		//4.提交事务
        		tx.commit();
        		//5.关闭资源
        		session.close();
        	}
        
        @Test
        	//为大明星写入一个角色
        	public void fun2(){
        		//1、获得session
        		Session session = HibernateUtils.openSession();
        		//2、开启事务
        		Transaction tx = session.beginTransaction();
        		//---------------------------------------------
        		//3.操作
        			//1。获得大明星用户
        			User user = session.get(User.class, 1l);
        			//2.创建公关角色
        			Role r = new Role();
        			r.setRole_name("公关");
        			//3.将角色添加到用户中
        			user.getRoles().add(r);
        			//4.将角色转为持久化
        			session.save(r);
        			
        		//-------------------------------------------
        		//4.提交事务
        		tx.commit();
        		//5.关闭资源
        		session.close();
        	}
        
        @Test
        	//为大明星解除一个角色
        	public void fun3(){
        		//1、获得session
        		Session session = HibernateUtils.openSession();
        		//2、开启事务
        		Transaction tx = session.beginTransaction();
        		//---------------------------------------------
        		//3.操作
        			//1。获得大明星用户
        			User user = session.get(User.class, 1l);
        			//2.获得要操作的角色对象
        			Role r1 = session.get(Role.class, 1l);
        			Role r2 = session.get(Role.class, 2l);
        			
        			//3.将角色从用户的角色集合中移除
        			user.getRoles().remove(r1);
        			user.getRoles().remove(r2);
        			
        		//-------------------------------------------
        		//4.提交事务
        		tx.commit();
        		//5.关闭资源
        		session.close();
        	}
        
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值