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

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

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

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

一对一

 

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

一、实现类

  1.Customer.java

    

  2.Order.java

    

二、配置文件

  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 package="com.jxlg.domain">
  6. <class name="Customer" table="t_customer">
  7. <id name="id" column="id">
  8. <generator class="native"></generator>
  9. </id>
  10. <property name="name" column="name" type="string"></property>
  11. <!--
  12. 一对多:一个客户(当前客户) 拥有 【多个订单】
  13. 表达一对多关系中的集合
  14. name:集合的属性名称
  15. inserse:是否将关系的维护反转给对方。默认值:false
  16. true:在Customer中放弃维护外键关系。
  17. -->
  18. <set name="orders" inverse="true">
  19. <!--
  20. key:用来描述外键
  21. column:外键的值
  22. -->
  23. <key column="cid"></key>
  24. <!--one-to-many 表达,Customer与orders的关系是一对多
  25. class:表达关联另一方的完整类名
  26. -->
  27. <one-to-many class="Order"/>
  28. </set>
  29. </class>
  30. </hibernate-mapping>
  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 package="com.jxlg.domain">
  6. <class name="Order" table="t_order">
  7. <id name="id" column="id">
  8. <generator class="native"></generator>
  9. </id>
  10. <property name="name" column="name" type="string"></property>
  11. <!-- 多对一:多个订单属于【一个客户】
  12. 表达多对一的关系
  13. name:引用的属性名称
  14. column:外键的列名
  15. class:我引用的Order的完整类名
  16. -->
  17. <many-to-one name="customer" column="cid" class="Customer"></many-to-one>
  18. </class>
  19. </hibernate-mapping>

三、一对多的操作

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

  1. package com.jxlg.onetomany;
  2.  
  3. import static org.junit.Assert.*;
  4.  
  5. import java.util.Set;
  6.  
  7. import org.hibernate.Session;
  8. import org.hibernate.Transaction;
  9. import org.junit.Test;
  10.  
  11. import com.jxlg.domain.Customer;
  12. import com.jxlg.domain.Order;
  13. import com.jxlg.util.HibernateUtils;
  14.  
  15. //测试一对多关系
  16. public class Demo1 {
  17.  
  18. //一对多关系的保存操作
  19. //共打印5条语句
  20. //前三条insert=》用来保存对象,维护外键
  21. //后两条update =》用来维护外键
  22. //解决:单纯的指定 关系由一方来维护,另一方不维护关系。
  23. //注意:外键维护的放弃,只能由非外键所在对象放弃。
  24. //Customer inverse=true
  25. //只打印三天语句 =》外键由order自己来维护
  26. @Test
  27. public void test1() {
  28. Session session = HibernateUtils.openSession();
  29. Transaction ts = session.beginTransaction();
  30. //----------------------------------------
  31. Customer cus = new Customer();
  32. cus.setName("jerry");
  33.  
  34. Order or1 = new Order();
  35. or1.setName("酱油");
  36. Order or2 = new Order();
  37. or2.setName("练习本");
  38.  
  39. //cus.getOrders().add(or1);//维护关系
  40. //cus.getOrders().add(or2);//维护关系
  41.  
  42. or1.setCustomer(cus);//维护关系
  43. or2.setCustomer(cus);//维护关系
  44.  
  45. session.save(cus);
  46. session.save(or1);
  47. session.save(or2);
  48. //----------------------------------------
  49. ts.commit();
  50. session.close();
  51. }
  52.  
  53. //多表关系 =》删除
  54. //删除 用户时,会先移除Customer中引用的外键,然后再删除Customer
  55. //结论:维护一方的对象时,会自动维护另一方的关系。
  56. //Customer 的inverse属性:true
  57. //会报错=》Customer不负责维护外键,直接删除Customer会导致,Order引用了无效的id,违反了外键约束。
  58. @Test
  59. public void test2() {
  60. Session session = HibernateUtils.openSession();
  61. Transaction ts = session.beginTransaction();
  62. //----------------------------------------
  63. Customer c = (Customer) session.get(Customer.class, 5);
  64.  
  65. //解决 :Customer 的inverse属性:true
  66. Set<Order> set = c.getOrders();
  67. for(Order o :set){
  68. o.setCustomer(null);//设置订单不属于任何Customer
  69. }
  70. session.delete(c);
  71. //----------------------------------------
  72. ts.commit();
  73. session.close();
  74. }
  75. //什么时候配置inverse属性?
  76. //主要看业务,如果一的一方经常需要维护外键 = 在1的一方不要配置inverse属性。
  77.  
  78. }

  3.2、级联操作

    在fun1中

      

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

  1. /测试 一对多关系
  2. public class Demo2 {
  3. @Test
  4. //增
  5. //我们希望在保存Customer时,自动将未保存的Orders当中的Order保存
  6. //cascade: save-update
  7. public void fun1(){
  8. Session session = HibernateUtils.openSession();
  9. session.beginTransaction();
  10. //------------------------------------------------
  11. Customer c = new Customer();
  12. c.setName("tom");
  13.  
  14. Order o1 = new Order();
  15. o1.setName("肥皂");
  16.  
  17. Order o2 = new Order();
  18. o2.setName("蜡烛");
  19.  
  20. c.getOrders().add(o1);//维护关系
  21. c.getOrders().add(o2); //维护关系
  22.  
  23. /*
  24. o1.setCustomer(c);//维护关系
  25. o2.setCustomer(c);//维护关系
  26. */
  27.  
  28. session.save(c);//保存对象
  29. //session.save(o1);//保存对象
  30. //session.save(o2);//保存对象
  31.  
  32. //------------------------------------------------
  33. session.getTransaction().commit();
  34. session.close(); // 游离状态
  35. }
  36. @Test
  37. //增
  38. //我们希望在保存Customer时,自动将未保存的Orders当中的Order保存
  39. //cascade: save-update
  40. public void fun2(){
  41. Session session = HibernateUtils.openSession();
  42. session.beginTransaction();
  43. //------------------------------------------------
  44.  
  45. Customer c = (Customer) session.get(Customer.class, 8);//1条 select
  46.  
  47. for(Order o :c.getOrders()){ // 1条 select
  48. o.setName("哇哈哈"); // 修改订单
  49. }
  50.  
  51. //------------------------------------------------
  52. session.getTransaction().commit();//因为设置级联修改,自动将订单的修改保存到数据
  53. //update语句
  54. session.close(); // 游离状态
  55. }
  56.  
  57. @Test
  58. //cascade: delete
  59. //删除Customer时 ,会将Customer下的订单一并删除
  60. //inverse : false 6条sql语句
  61. //inverse : true 5条sql语句 比上面少一条维护外键
  62.  
  63. public void fun3(){
  64. Session session = HibernateUtils.openSession();
  65. session.beginTransaction();
  66. //------------------------------------------------
  67.  
  68. Customer c = (Customer) session.get(Customer.class, 7);//1条 select
  69.  
  70. session.delete(c);//删除Customer
  71. // 删除两个Order
  72.  
  73. //------------------------------------------------
  74. session.getTransaction().commit();
  75.  
  76. session.close(); // 游离状态
  77. }
  78.  
  79. @Test
  80. //cascade: delete
  81. //操作的两方cascade值都为delete
  82. //需要注意: 千万不要在两方都配置 级联删除. 删除任何一方,会导致整个关系链对象全部删除.
  83. public void fun4(){
  84. Session session = HibernateUtils.openSession();
  85. session.beginTransaction();
  86. //------------------------------------------------
  87. Order o = (Order) session.get(Order.class, 9);//select
  88.  
  89. session.delete(o);//delete删除当前order
  90.  
  91. //找到所有关联的Customer删除 select
  92. // delete Customer
  93. // Customer配置了级联删除=> select 找下面的order
  94. // 删除所有Order
  95. //删除Customer
  96.  
  97. //------------------------------------------------
  98. session.getTransaction().commit();
  99.  
  100. session.close(); // 游离状态
  101. }
  102. }

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

  1. public class Demo3 {
  2. @Test
  3. //inverse:false
  4. //cascade: delete-orphan 孤儿删除 => 当没有任何外键引用Order时,order 会被删除
  5. public void fun1(){
  6. Session session = HibernateUtils.openSession();
  7. session.beginTransaction();
  8. //------------------------------------------------
  9. Customer c = (Customer) session.get(Customer.class, 9);
  10. Iterator<Order> it = c.getOrders().iterator();
  11. //注意: 删除Customer下的订单时,不能使用 c.setOrders(null); c.setOrders(new HashSet());
  12. while(it.hasNext()){ // 遍历Customer下的订单,并将订单删除 => 维护关系
  13. it.next();
  14. it.remove();
  15. }
  16. //------------------------------------------------
  17. session.getTransaction().commit();
  18. session.close(); // 游离状态
  19. }
  20.  
  21. } 

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

  1. /测试 一对多关系
  2. public class Demo4 {
  3. @Test
  4. //cascade: all-delete-orphan => 相当于配置 save-update,delete,delete-orphan
  5. public void fun1(){
  6. Session session = HibernateUtils.openSession();
  7. session.beginTransaction();
  8. //------------------------------------------------
  9. Customer c = new Customer();
  10. c.setName("tom");
  11.  
  12. Order o1 = new Order();
  13. o1.setName("肥皂");
  14.  
  15. Order o2 = new Order();
  16. o2.setName("蜡烛");
  17.  
  18. c.getOrders().add(o1);//维护关系
  19. c.getOrders().add(o2); //维护关系
  20.  
  21. session.save(c);
  22. //------------------------------------------------
  23. session.getTransaction().commit();
  24. session.close(); // 游离状态
  25. }
  26. @Test
  27. //cascade: all-delete-orphan => 相当于配置 save-update,delete,delete-orphan
  28. public void fun2(){
  29. Session session = HibernateUtils.openSession();
  30. session.beginTransaction();
  31. //------------------------------------------------
  32. Customer c = (Customer) session.get(Customer.class, 10);
  33. session.delete(c);
  34. //------------------------------------------------
  35. session.getTransaction().commit();
  36. session.close(); // 游离状态
  37. }
  38.  
  39. @Test
  40. //cascade: all-delete-orphan => 相当于配置 save-update,delete,delete-orphan
  41. public void fun3(){
  42. Session session = HibernateUtils.openSession();
  43. session.beginTransaction();
  44. //------------------------------------------------
  45. Customer c = (Customer) session.get(Customer.class, 12);
  46.  
  47. Iterator<Order> it = c.getOrders().iterator();
  48.  
  49. while(it.hasNext()){ // 遍历Customer下的订单,并将订单删除 => 维护关系
  50. it.next();
  51. it.remove();
  52. }
  53.  
  54. //------------------------------------------------
  55. session.getTransaction().commit();
  56. session.close(); // 游离状态
  57. }
  58. }

   联级操作总结:

        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. ASP.NET Core Web应用在发布时选择是否对视图进行编译

    原文:ASP.NET Core Web应用在发布时选择是否对视图进行编译 在我们发布ASP.NET Core Web应用程序时,选择以文件形式发布,发布方法选择文件系统 默认情况下,会把Views的视 ...

  2. exe4j 打包(多个jar打包)

    一,自行下载exe4j 注册码: 用户名和公司名可随便填A-XVK258563F-1p4lv7mg7savA-XVK209982F-1y0i3h4ywx2h1A-XVK267351F-dpurrhny ...

  3. 用AJAX传值参数是中文时可能会乱码

    1.ajax代码 function SelectSemesterBySchYear() { // alert('sssssss'); var temp1 = document.getElementBy ...

  4. 安装keepalived 出现configure: error: Popt libraries is required

    keepalived执行./configure --prefix=/usr/local/keepalived时报错:configure: error: Popt libraries is requir ...

  5. 人脸识别--Open set和Close set的区别

    训练和测试人脸识别分类器时,总会提到Open-set和Close-set.这俩词到底是什么概念呢?有什么区别呢? 所谓close-set,就是所有的测试集都在训练集中出现过.所以每次的预测直接得出测试 ...

  6. canvas像素的操作

    ###在canvas中的像素操作 到目前为止,我们尚未深入了解Canvas画布真实像素的原理,事实上, 你可以直接通过ImageData对象操纵像素数据,直接读取或将数据数组写入该对象中 ###得到场 ...

  7. SpringBoot 非web项目简单架构

    1.截图 2.DemoService package com.github.weiwei02.springcloudtaskdemo; import org.springframework.beans ...

  8. sql语句之分组

    对聚合函数的结果进行筛选用having,不能用where

  9. thinkphp cbd模式

    ThinkPHP从3.0版本开始引入了全新的CBD(核心Core+行为Behavior+驱动Driver)架构模式,因为从底层开始,框架就采用核心+行为+驱动的架构体系,核心保留了最关键的部分,并在重 ...

  10. P1934 封印

    P1934 封印 题目描述 很久以前,魔界大旱,水井全部干涸,温度也越来越高.为了拯救居民,夜叉族国王龙溟希望能打破神魔之井,进入人界“窃取”水灵珠,以修复大地水脉.可是六界之间皆有封印,神魔之井的封 ...