Hibernate学习笔记(五)多表设计

多表关系

  1. 一对多
    在这里插入图片描述

  2. 多对多
    在这里插入图片描述

  3. 一对一
    在这里插入图片描述

一对多设计

  1. 创建实体类
    在这里插入图片描述
  2. 配置文件
    Customer.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">
<!-- ORM元数据  表对象关系映射文件 
    	package : 配置该配置文件中类所在的包.  -->
<hibernate-mapping package="com.lwb.domain">
	<class name="com.lwb.domain.Customer" table="t_customer" >
		<id name="id" column="id">
			<!-- generator:主键生成策略 -->
			<generator class="native"></generator>
		</id>
		<!-- property : 实体中属性与表中列的对应
			 name : 实体中属性名称
			 column : 表中列的名称
			 length : 数据长度
			 -->
		<property name="name" column="name" type="string"></property>
		<!-- 表达一对多的集合 -->
		<!-- name:集合的属性名称 -->
		<set name="Order">
			<!-- key:用来描述外键的
			  column:外键的值
			 -->
			<key column="cid"></key>
			<!-- one-to-many 表达:Customer与Order的关系是一对多
				class:表达关联的另一方的完整类名
			 -->
			<one-to-many class="Order"/>
		</set>
	</class>
</hibernate-mapping>

Order.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">
<!-- ORM元数据  表对象关系映射文件 
    	package : 配置该配置文件中类所在的包.  -->
<hibernate-mapping package="com.lwb.domain">
	<class name="com.lwb.domain.Order" table="t_order" >
		<id name="id" column="id">
			<!-- generator:主键生成策略 -->
			<generator class="native"></generator>
		</id>
		<!-- property : 实体中属性与表中列的对应
			 name : 实体中属性名称
			 column : 表中列的名称
			 length : 数据长度
			 -->
		<property name="name" column="name" type="string"></property>
		<!-- 表达多对一的关系 -->
		<!-- name:引用属性名称
			column:外键的键名
			class:我引用的Customer的完整名称
		-->
		<many-to-one name="customer" column="cid" class="Customer"></many-to-one>

	</class>
</hibernate-mapping>

hibernate.cfg.xml
在这里插入图片描述

  1. 测试案例
Session session = HibernateUtils.openSession();
		session.beginTransaction();
		//创建对象
		Customer c = new Customer();
		Order o1 = new Order();
		Order o2 = new Order();
		c.setName("lwb");
		o1.setName("哑铃");
		o2.setName("篮球");
		//维护关系
		c.getOrder().add(o1);
		c.getOrder().add(o2);
		//保存对象
		session.save(c);
		session.save(o1);
		session.save(o2);
		
		
		session.getTransaction().commit();
		session.clear();

在这里插入图片描述

在这里插入图片描述

  1. 优化创建
@Test
	//1 测试1对多关系中,保存操作
	//共打印5条语句
	//前3条打印insert	=> 保存对象,维护外键
	//后两条打印update => 维护外键
	//解决=>  单纯指定 关系由其中一方来维护.另一方不维护关系.
	//注意=> 外键维护的放弃,只能由非外键所在对象来放弃.
	//Customer  inverse属性: true
	//只打印3条语句=> 外键由order自己来维护
	public void test1(){
		Session session = HibernateUtils.openSession();
		session.beginTransaction();
		//创建对象
		Customer c = new Customer();
		Order o1 = new Order();
		Order o2 = new Order();
		c.setName("lwb");
		o1.setName("哑铃");
		o2.setName("篮球");
		//维护关系
		//c.getOrder().add(o1);
		//c.getOrder().add(o2);
		o1.setCustomer(c);
		o2.setCustomer(c);
		//保存对象
		session.save(c);
		session.save(o1);
		session.save(o2);
		
		
		session.getTransaction().commit();
		session.clear();
	}

在这里插入图片描述

  1. 多表删除
    • 删除Customer时 ,会先移除 Customer中引用的外键.然后再删除Customer
    • 结论: 维护一方的对象时,会自动维护另一方的关系
//多表关系=> 删除
	//删除Customer时 ,会先移除 Customer中引用的外键.然后再删除Customer
	// 结论: 维护一方的对象时,会自动维护另一方的关系
	// Customer 的 inverse属性: true
	// 会报错 => Customer不负责维护外键, 直接删除Customer 会导致,order引用了无效的id.违反了外键约束.
	@Test
	public void fun2(){
		Session session = HibernateUtils.openSession();
		session.beginTransaction();
		//------------------------------------------------
		
		Customer c = (Customer) session.get(Customer.class, 3);
		
		// Customer 的 inverse属性: true 
		
		Set<Order> set = c.getOrders();
		for(Order o : set){
			o.setCustomer(null);//设置订单不属于任何Customer
		}
		
		session.delete(c);
		
		//------------------------------------------------
		session.getTransaction().commit();
		session.close(); // 游离状态
	}

级联操作

  1. cascade属性
    • save-update:级联保存,级联修改
    • delete:删除A,同时删除B,AB都不存在
    • delete-orphan:孤儿删除,解除关系,同时将B删除,A存在的。
    • 如果需要配置多项,使用逗号分隔。< set cascade=“save-update,delete” >
    • all : save-update 和 delete 整合
    • all-delete-orphan : 三个整合
  2. 操作代码:
//测试 一对多关系
public class Demo2 {
	@Test
	//增
	//我们希望在保存Customer时,自动将未保存的Orders当中的Order保存
	//cascade: save-update
	public void fun1(){
		Session session = HibernateUtils.openSession();
		session.beginTransaction();
		//------------------------------------------------
		Customer c = new Customer();
		c.setName("tom");
		
		Order o1 = new Order();
		o1.setName("肥皂");
		
		Order o2 = new Order();
		o2.setName("蜡烛");
		
		c.getOrders().add(o1);//维护关系
		c.getOrders().add(o2); //维护关系
		
		
		/*
		o1.setCustomer(c);//维护关系
		o2.setCustomer(c);//维护关系
		 */		
		
		session.save(c);//保存对象
		//session.save(o1);//保存对象
		//session.save(o2);//保存对象
		
		//------------------------------------------------
		session.getTransaction().commit();
		session.close(); // 游离状态
	}
	@Test
	//增
	//我们希望在保存Customer时,自动将未保存的Orders当中的Order保存
	//cascade: save-update
	public void fun2(){
		Session session = HibernateUtils.openSession();
		session.beginTransaction();
		//------------------------------------------------
		
		Customer c = (Customer) session.get(Customer.class, 8);//1条 select
		
		for(Order o :c.getOrders()){ // 1条 select
			o.setName("哇哈哈"); // 修改订单
		}
		
		//------------------------------------------------
		session.getTransaction().commit();//因为设置级联修改,自动将订单的修改保存到数据
										  //update语句
		session.close(); // 游离状态
	}
	
	@Test
	//cascade: delete
	//删除Customer时 ,会将Customer下的订单一并删除
	//inverse : false   6条sql语句   
	//inverse : true    5条sql语句 比上面少一条维护外键
			
	public void fun3(){
		Session session = HibernateUtils.openSession();
		session.beginTransaction();
		//------------------------------------------------
		
		Customer c = (Customer) session.get(Customer.class, 7);//1条 select
		
		
		session.delete(c);//删除Customer
						 // 删除两个Order
		
		//------------------------------------------------
		session.getTransaction().commit();
										  
		session.close(); // 游离状态
	}
	
	@Test
	//cascade: delete
	//操作的两方cascade值都为delete
	//需要注意: 千万不要在两方都配置 级联删除. 删除任何一方,会导致整个关系链对象全部删除.
	public void fun4(){
		Session session = HibernateUtils.openSession();
		session.beginTransaction();
		//------------------------------------------------
		Order o  = (Order) session.get(Order.class, 9);//select
		
		session.delete(o);//delete删除当前order
		
							//找到所有关联的Customer删除 select
							// delete Customer
							// Customer配置了级联删除=> select 找下面的order
							// 删除所有Order
							//删除Customer
		
		//------------------------------------------------
		session.getTransaction().commit();
										  
		session.close(); // 游离状态
	}
}

@Test
	//inverse:false
	//cascade: delete-orphan 孤儿删除 => 当没有任何外键引用Order时,order 会被删除
	public void fun5(){
		Session session = HibernateUtils.openSession();
		session.beginTransaction();
		//------------------------------------------------
			Customer c = (Customer) session.get(Customer.class, 9);
			Iterator<Order> it = c.getOrders().iterator();
			//注意: 删除Customer下的订单时,不能使用 c.setOrders(null); c.setOrders(new HashSet());
			while(it.hasNext()){ // 遍历Customer下的订单,并将订单删除 => 维护关系
				it.next();
				it.remove();
			}
			//------------------------------------------------
			session.getTransaction().commit();
			session.close(); // 游离状态
	}

多对多设计

  1. 表关系
    在这里插入图片描述

  2. 对象关系
    在这里插入图片描述

  3. 配置文件

    • 配置多对多关系:
      • set:表达集合
        • name:集合的属性名
        • table:配置多对多中间表的名称
      • key:表达外键
        • column:表示外键名
      • many-to-many:表达多对多关系
        • class:集合引用方的类
        • column:对方在中间表的外键名

student.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 package="com.lwb.domain">
	<class name="com.lwb.domain.Student" table="t_student" >

		<id name="id" column="id">
			<!-- generator:主键生成策略 -->
			<generator class="native"></generator>
		</id>
		<property name="name" column="name"></property>
		<!-- 多对多关系 -->
		<!-- set:表达集合
				name:集合的属性名
			key:表达外键
				column:表示外键名
			many-to-many:表达多对多关系
				class:集合引用方的类
				column:对方在中间表的外键名		
		 -->
		<set name="courses" table="t_student_course">
			<key column="sid"></key>
			<many-to-many class="Course" column="cid"></many-to-many>
		</set>
	</class>
</hibernate-mapping>

Course.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 package="com.lwb.domain">
	<class name="com.lwb.domain.Course" table="t_course" >

		<id name="id" column="id">
			<!-- generator:主键生成策略 -->
			<generator class="native"></generator>
		</id>
		<property name="name" column="name"></property>
		<!-- 多对多关系 -->
		<!-- set:表达集合
				name:集合的属性名
			key:表达外键
				column:表示外键名
			many-to-many:表达多对多关系
				class:集合引用方的类
				column:对方在中间表的外键名		
		 -->
		<set name="students" table="t_student_course">
			<key column="cid"></key>
			<many-to-many class="Student" column="sid"></many-to-many>
		</set>
	</class>
</hibernate-mapping>

配置hibernate.cfg.xml
在这里插入图片描述

  1. 测试:
    在这里插入图片描述

  2. 多对多操作说明:

    • 保存学生:通过学生保存课程,有学生维护外键
      • student.hbm.xml配置:
        • inverse = false
        • cascade = save-update
      • course.hbm.xml配置:
        • inverse = true
          在这里插入图片描述
          在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值