既然我们讲到了一对多和多对一关系,必然要提到多表设计的问题。在开发中,前期需要进行需求分析,希求分析提供E-R图,根据ER图编写表结构。

我们知道表之间关系存在三种:

一对多&多对一:1表(主表)必须主键 和 多表(从表)必须外键,主表的主键 与 从表外键 形成主外键关系

多对多:提供中间表(从表),提供2个字段(外键)分别对应两个主表。

一对一

 

下面演示的是一对多&多对一的关系,和上面写的那样使用Customer和Order之间的关系来举例子。

一、实现类

  1.Customer.java

    

  2.Order.java

    

二、配置文件

<?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.jxlg.domain">
<class name="Customer" table="t_customer">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="name" column="name" type="string"></property>
<!--
一对多:一个客户(当前客户) 拥有 【多个订单】
表达一对多关系中的集合
name:集合的属性名称
inserse:是否将关系的维护反转给对方。默认值:false
true:在Customer中放弃维护外键关系。
-->
<set name="orders" inverse="true">
<!--
key:用来描述外键
column:外键的值
-->
<key column="cid"></key>
<!--one-to-many 表达,Customer与orders的关系是一对多
class:表达关联另一方的完整类名
-->
<one-to-many class="Order"/>
</set>
</class>
</hibernate-mapping>
<?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.jxlg.domain">
<class name="Order" table="t_order">
<id name="id" column="id">
<generator class="native"></generator>
</id>
<property name="name" column="name" type="string"></property>
<!-- 多对一:多个订单属于【一个客户】
表达多对一的关系
name:引用的属性名称
column:外键的列名
class:我引用的Order的完整类名
-->
<many-to-one name="customer" column="cid" class="Customer"></many-to-one>
</class>
</hibernate-mapping>

三、一对多的操作

3.1、一对多关系的基本操作

package com.jxlg.onetomany;

import static org.junit.Assert.*;

import java.util.Set;

import org.hibernate.Session;
import org.hibernate.Transaction;
import org.junit.Test; import com.jxlg.domain.Customer;
import com.jxlg.domain.Order;
import com.jxlg.util.HibernateUtils; //测试一对多关系
public class Demo1 { //一对多关系的保存操作
//共打印5条语句
//前三条insert=》用来保存对象,维护外键
//后两条update =》用来维护外键
//解决:单纯的指定 关系由一方来维护,另一方不维护关系。
//注意:外键维护的放弃,只能由非外键所在对象放弃。
//Customer inverse=true
//只打印三天语句 =》外键由order自己来维护
@Test
public void test1() {
Session session = HibernateUtils.openSession();
Transaction ts = session.beginTransaction();
//----------------------------------------
Customer cus = new Customer();
cus.setName("jerry"); Order or1 = new Order();
or1.setName("酱油");
Order or2 = new Order();
or2.setName("练习本"); //cus.getOrders().add(or1);//维护关系
//cus.getOrders().add(or2);//维护关系 or1.setCustomer(cus);//维护关系
or2.setCustomer(cus);//维护关系 session.save(cus);
session.save(or1);
session.save(or2);
//----------------------------------------
ts.commit();
session.close();
} //多表关系 =》删除
//删除 用户时,会先移除Customer中引用的外键,然后再删除Customer
//结论:维护一方的对象时,会自动维护另一方的关系。
//Customer 的inverse属性:true
//会报错=》Customer不负责维护外键,直接删除Customer会导致,Order引用了无效的id,违反了外键约束。
@Test
public void test2() {
Session session = HibernateUtils.openSession();
Transaction ts = session.beginTransaction();
//----------------------------------------
Customer c = (Customer) session.get(Customer.class, 5); //解决 :Customer 的inverse属性:true
Set<Order> set = c.getOrders();
for(Order o :set){
o.setCustomer(null);//设置订单不属于任何Customer
}
session.delete(c);
//----------------------------------------
ts.commit();
session.close();
}
//什么时候配置inverse属性?
//主要看业务,如果一的一方经常需要维护外键 = 在1的一方不要配置inverse属性。 }

  3.2、级联操作

    在fun1中

      

测试一:cascade的值为:save-update、delete

/测试 一对多关系
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(); // 游离状态
}
}

测试二:cascade的值为:delete-orphan

public class Demo3 {
@Test
//inverse:false
//cascade: delete-orphan 孤儿删除 => 当没有任何外键引用Order时,order 会被删除
public void fun1(){
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(); // 游离状态
} } 

  测试三: cascade的值为:all-delete-orphan

/测试 一对多关系
public class Demo4 {
@Test
//cascade: all-delete-orphan => 相当于配置 save-update,delete,delete-orphan
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); //维护关系 session.save(c);
//------------------------------------------------
session.getTransaction().commit();
session.close(); // 游离状态
}
@Test
//cascade: all-delete-orphan => 相当于配置 save-update,delete,delete-orphan
public void fun2(){
Session session = HibernateUtils.openSession();
session.beginTransaction();
//------------------------------------------------
Customer c = (Customer) session.get(Customer.class, 10);
session.delete(c);
//------------------------------------------------
session.getTransaction().commit();
session.close(); // 游离状态
} @Test
//cascade: all-delete-orphan => 相当于配置 save-update,delete,delete-orphan
public void fun3(){
Session session = HibernateUtils.openSession();
session.beginTransaction();
//------------------------------------------------
Customer c = (Customer) session.get(Customer.class, 12); Iterator<Order> it = c.getOrders().iterator(); while(it.hasNext()){ // 遍历Customer下的订单,并将订单删除 => 维护关系
it.next();
it.remove();
} //------------------------------------------------
session.getTransaction().commit();
session.close(); // 游离状态
}
}

   联级操作总结:

        save-update:A保存,同时保存B

        delete:删除A,同时删除B,AB都不存在

        delete-orphan:孤儿删除,解除关系,同时将B删除,A存在的。

        如果需要配置多项,使用逗号分隔。<set cascade="save-update,delete">

        all : save-update 和 delete 整合

        all-delete-orphan : 三个整合

Hibernate(五)之一对多&多对一映射关系的更多相关文章

  1. hibernate(四) 双向多对多映射关系

    序言 莫名长了几颗痘,真TM疼,可能是现在运动太少了,天天对着电脑,决定了,今天下午花两小时去跑步了, 现在继上一章节的一对多的映射关系讲解后,今天来讲讲多对多的映射关系把,明白了一对多,多对多个人感 ...

  2. Hibernate学习(四)———— 双向多对多映射关系

    一.小疑问的解答 问题一:到这里,有很多学习者会感到困惑,因为他不知道使用hibernate是不是需要自己去创建表,还是hibernate全自动,如果需要自己创建表,那么主外键这种设置也是自己设置吗? ...

  3. hibernate笔记--单(双)向的多对多映射关系

    在讲单向的多对多的映射关系的案例时,我们假设我们有两张表,一张角色表Role,一张权限表Function,我们知道一个角色或者说一个用户,可能有多个操作权限,而一种操作权限同时被多个用户所拥有,假如我 ...

  4. Hibernate 中一对多和多对多映射

    1. 一对多映射 1.1 JavaWeb 一对多建表原则 多方表的外键指向一方表的主键; 1.2 编写一对多的 JavaBean // 客户(一方)和联系人(多方) // 客户(一方) JavaBea ...

  5. Hibernate第六篇【多对多映射、一对一映射】

    前言 前面已经讲解了一对多和多对一的映射是怎么配置了,也讲解了inverse和cascade属性对关联关系的影响,本博文讲解多对多的映射和一对一的映射! 多对多映射 需求:一个项目由多个员工开发,一个 ...

  6. java框架篇---hibernate(多对多)映射关系

    以学生和老师为例的来讲解多对多映射. 实体类: Student package cn.itcast.g_hbm_manyToMany; import java.util.HashSet; import ...

  7. Hibernate的多对多映射关系

    example: 老师(teacher)和学生(Student)就是一个多对多的关系吧?老师可以有多个学生,学生也可以由多个老师,那在Hibernate中多对多是怎样实现的呢?? 在Hibernate ...

  8. hibernate多对多映射关系实现

    Course.hbm.xml: <?xml version="1.0"?><!DOCTYPE hibernate-mapping PUBLIC        &q ...

  9. Hibernate的执行流程和集合的映射关系

    Hibernate的执行流程 集合映射 准被hibernate的运行环境 配置hibernate.cfg.xml主配置文件 1.Set集合 写User.java类 package com.gqx.co ...

随机推荐

  1. python 数据结构之冒泡排序

    def bubble_sort(alist): # 外层循环冒泡排序进行的次数(len-1) for i in range(len(alist) - 1, 0, -1): # 内层循环控制冒泡的比较: ...

  2. 20-Ubuntu-文件和目录命令-查看目录树型结构-tree

    tree 以树状图列出当前目录下的文件目录结构 选项 含义 -d 只显示当前目录的子目录树型结构   显示当前目录的子目录和文件树型结构 例: 1.查看文档目录下的子目录和文件树型结构 2.查看文档目 ...

  3. 2018-12-22-WPF-在绑定表达式添加计算

    title author date CreateTime categories WPF 在绑定表达式添加计算 lindexi 2018-12-22 16:12:56 +0800 2018-12-22 ...

  4. 详解redis服务

    http://mp.weixin.qq.com/s?__biz=MzIyMDA1MzgyNw==&mid=2651968327&idx=1&sn=6e6cb01d334d7ae ...

  5. override和overload区别

    方法重载(overload)实现的是编译时的多态性(也称为前绑定) 方法重写(override)实现的是运行时的多态性(也称为后绑定)

  6. JS去重算法

    1.遍历数组法 它是最简单的数组去重方法(indexOf方法) 实现思路:新建一个数组,遍历去要重的数组,当值不在新数组的时候(indexOf为-1)就加入该新数组中: var arr=[2,8,5, ...

  7. BeanPostProcessor原理--使用讲解

    <Spring源码解析>笔记 BeanPostProcessor原理学习 在学习BeanPostProcessor的原理学习完之后,对Spring如何使用充满好奇,尝试使用例子进行理解,以 ...

  8. [JZOJ3303] 【集训队互测2013】城市规划

    题目 题目大意 求\(N\)个点的简单无向图的方案数(有编号). 结果对\(1004535809\)取模. 思考历程 感觉这个问题非常经典. 当时想到了一堆式子,但都觉得可能会有重和漏,于是弃掉了-- ...

  9. [JZOJ 5782] 城市猎人

    思路: 并查集按秩合并维护出现时间. 最早连接时间就是树上连接最大值. \(qwq\)我居然把路径压缩和按秩合并打到一个程序里了...OvO #include <bits/stdc++.h> ...

  10. 牛客多校第五场 A digits 2 签到

    题意: 给定一个n,输出一个数,要求这个数所有位之和整除n,并且这个数也整除n,并且位数不许多于1e4 题解: 把这个数n输出n遍. #include<iostream> using na ...