当前位置: 首页 > news >正文

Hibernate(五)之一对多多对一映射关系

既然我们讲到了一对多和多对一关系,必然要提到多表设计的问题。在开发中,前期需要进行需求分析,希求分析提供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 : 三个整合

转载于:https://www.cnblogs.com/Jeely/p/11226465.html

相关文章:

  • Windows 7的预备知识系列之二:认识Windows 7中的窗口
  • [jquery]this触发自身click事件,当前控件向上滑出
  • 转:获取网页URL地址及参数等的两种方法(js和C#)
  • 前后端数据交互的方式有哪些?
  • MongoDB.Mastering_Find()
  • windows7编程-任务栏进度条
  • CRC8算法DELPHI源码
  • NHibernate 快速入门(四)使用 HQL 查询数据
  • HashMap底层实现原理
  • Location Aware DNS Server-----项目部署说明
  • pyqt 调用QT设计师创建的对话框
  • 艾伟_转载:下载文件时根据MIME类型自动判断保存文件的扩展名
  • Oracle学习手札
  • 艾伟_转载:把委托说透(1):开始委托之旅 委托与接口
  • centos7常见问题(更新。。。)
  • 自己简单写的 事件订阅机制
  • [译] 怎样写一个基础的编译器
  • 230. Kth Smallest Element in a BST
  • android百种动画侧滑库、步骤视图、TextView效果、社交、搜房、K线图等源码
  • Effective Java 笔记(一)
  • Facebook AccountKit 接入的坑点
  • fetch 从初识到应用
  • GDB 调试 Mysql 实战(三)优先队列排序算法中的行记录长度统计是怎么来的(上)...
  • interface和setter,getter
  • java中具有继承关系的类及其对象初始化顺序
  • js正则,这点儿就够用了
  • maven工程打包jar以及java jar命令的classpath使用
  • Yeoman_Bower_Grunt
  • 使用权重正则化较少模型过拟合
  • 网页视频流m3u8/ts视频下载
  • 一个SAP顾问在美国的这些年
  • mysql 慢查询分析工具:pt-query-digest 在mac 上的安装使用 ...
  • 容器镜像
  • ​LeetCode解法汇总2304. 网格中的最小路径代价
  • #1015 : KMP算法
  • (android 地图实战开发)3 在地图上显示当前位置和自定义银行位置
  • (C语言)球球大作战
  • (python)数据结构---字典
  • (介绍与使用)物联网NodeMCUESP8266(ESP-12F)连接新版onenet mqtt协议实现上传数据(温湿度)和下发指令(控制LED灯)
  • (原創) 如何將struct塞進vector? (C/C++) (STL)
  • (转)3D模板阴影原理
  • (转)为C# Windows服务添加安装程序
  • (状压dp)uva 10817 Headmaster's Headache
  • .NET CORE 第一节 创建基本的 asp.net core
  • .net FrameWork简介,数组,枚举
  • .NET Framework杂记
  • .NET Remoting学习笔记(三)信道
  • .NET 发展历程
  • .NET/C# 获取一个正在运行的进程的命令行参数
  • .net利用SQLBulkCopy进行数据库之间的大批量数据传递
  • .pings勒索病毒的威胁:如何应对.pings勒索病毒的突袭?
  • @EnableAsync和@Async开始异步任务支持
  • @取消转义
  • [120_移动开发Android]008_android开发之Pull操作xml文件
  • [C++]:for循环for(int num : nums)