级联保存或更新CASCADE

级联保存或更新:

  作用就是:保存一方的数据的时候,会把关联的对象也同时保存。

级联保存或更新的配置:

    属性名:cascade

        属性值:

            1.none:所有情况下均不进行关联操作。(默认值)

            2.save-update:在执行save/update/saveOrUpdate时进行关联操作

            3.delete:在执行delete时进行关联操作

            4.all-delete-orphan:当一个节点在对象图中成为孤儿节点时,删除该节点

            5.all:所有情况下均进行关联操作,即save-update和delete(但是不推荐,避免删除后级联删除最后导致莫名其妙少了很多数据)

先贴上一段代码:

    这段代码是上一章的代码,作用是创建新用户并且创建两个订单添加到该客户中。

    新创建的对象都是瞬时状态,我们保存到数据库需要将对象进行持久化操作。

    这里发现,最后持久化对象用了三行代码。

     session.save(cst); session.save(od); session.save(od1);

    又保存客户,又保存两个订单,感觉代码有点多。但是不执行后两个行代码又不行,瞬时状态的怎么可以!

    所以我们就得设置级联操作了,这样就可以保存某一方的同时,自动保存或更新级联的对象。

/**
* 创建新用户并且创建两个订单添加到该客户中
*/
@Test
public void fun1(){
Session session = HibernateUtils.getSession();
session.getTransaction().begin(); try {
//新建用户 瞬时状态
Customer cst = new Customer();
cst.setCust_id(1);
cst.setCust_name("台用胜");
cst.setCust_gender("男");
cst.setCust_age(24);
cst.setCust_phone("18736549531"); //新建订单 瞬时状态
Order od = new Order();
od.setOrder_id(UUID.randomUUID().toString());
od.setDetail_id(UUID.randomUUID().toString()); Order od1 = new Order();
od1.setOrder_id(UUID.randomUUID().toString());
od1.setDetail_id(UUID.randomUUID().toString()); //表达客户和订单的关系
cst.getOds().add(od);
cst.getOds().add(od1);
//表达订单和客户的关系
od.setCst(cst);
od1.setCst(cst);
//持久化用户和订单
session.save(cst);
session.save(od);
session.save(od1);
} catch (Exception e) {
session.getTransaction().rollback();
e.printStackTrace();
} session.getTransaction().commit();
}

级联保存或更新的操作:

  这里有客户对订单的关系,上述中,给客户添加订单需要三行代码。

  这三行代码中, 如果我们认为客户方是“主控方”那么后面的两行代码我们就可以省略,如果我们认为订单方是“主控方”那么第一行的代码就可以省略。具体看代码

  那我就举一个例子,选择客户方是“主控方”,

  1.配置Customer.hbm.xml(在配置的时候添加cascade="save-update")

<?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="deep.domain">
<class name="Customer" table="customera">
<id name="cust_id" column = "cust_id">
<generator class="native"></generator>
</id> <property name="cust_name" column = "cust_name"></property>
<property name="cust_gender" column = "cust_gender"></property>
<property name="cust_age" column = "cust_age"></property>
<property name="cust_phone" column = "cust_phone"></property> <!-- 配置一对多属性 -->
<set name="ods" cascade="save-update">
<key column="cust_order_id" ></key>
<one-to-many class="Order"/>
</set> </class> </hibernate-mapping>

2.随后将上面粘贴的java代码进行修改(我们会发现,少了session.save(od)和session.save(od1)),但是效果是一样的

/**
* 级联保存或更新
* 创建新用户并且创建两个订单添加到该客户中
*/
@Test
public void fun2(){
Session session = HibernateUtils.getSession();
session.getTransaction().begin(); try {
//新建用户 瞬时状态
Customer cst = new Customer();
cst.setCust_id(1);
cst.setCust_name("台用胜");
cst.setCust_gender("男");
cst.setCust_age(24);
cst.setCust_phone("18736549531"); //新建订单 瞬时状态
Order od = new Order();
od.setDetail_id(UUID.randomUUID().toString()); Order od1 = new Order();
od1.setDetail_id(UUID.randomUUID().toString()); //表达客户和订单的关系
cst.getOds().add(od);
cst.getOds().add(od1);
//表达订单和客户的关系
od.setCst(cst);
od1.setCst(cst); //持久化用户和订单
session.save(cst);
} catch (Exception e) {
session.getTransaction().rollback();
e.printStackTrace();
} session.getTransaction().commit();
}

同样,如果我们认为订单方是“主控方”,那么就只要这样配置

<!-- 配置多对一属性 -->
<many-to-one name="cst" class="Customer" column="cust_order_id" cascade="save-update" />

随后的java代码是:(获取主键值为 6的客户,并新建两个订单添加到该客户中)

/**
* 级联保存或更新
* 获取用户并且创建两个订单添加到该客户中
*/
@Test
public void fun3(){
Session session = HibernateUtils.getSession();
session.getTransaction().begin(); try {
//获取主键值为6的客户 瞬时状态
Customer cst = session.get(Customer.class, 6); //新建订单 瞬时状态
Order od = new Order();
od.setDetail_id(UUID.randomUUID().toString()); Order od1 = new Order();
od1.setDetail_id(UUID.randomUUID().toString()); //表达客户和订单的关系
cst.getOds().add(od);
cst.getOds().add(od1);
//表达订单和客户的关系
od.setCst(cst);
od1.setCst(cst); //持久化用户和订单
session.save(od);
session.save(od1);
} catch (Exception e) {
session.getTransaction().rollback();
e.printStackTrace();
} session.getTransaction().commit();
}

刚刚上面的是两种单一方向,也可以认为订单方和客户方都是“主控方”,方法自然很简单,就是在两边都加上cascade="save-update"啦~

到这里cascade概念基本可以了,我也算是有点理解了吧,这样确实方便很多,少了代码量,也比较人性化。

问题:我的订单表中的主键这是的是uuid,在配置文件中设置了主键自增策略是uuid,在创建新订单的时候,我有一个订单.setId的动作,并且手动生成了uuid。 在我没有级联操作的时候,能够正常添加订单,但是级联操作后就会报错,java代码和报错代码如下(我认为客户方是“主控方”)

错误明细:

 十一月 18, 2018 4:31:07 下午 org.hibernate.internal.SessionImpl$5 mapManagedFlushFailure
ERROR: HHH000346: Error during managed flush [Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1]

百度查了也没搞懂是怎么回事,想了有一会儿,然后报错,看到错误来源sql语句update的第一个参数,我就看到了我java中,然后猜测是主键策略方面的问题,我就尝试把那一行代码删除,发现可以运行,但是不知道为什么。如果有大佬知道希望能指点一二。。谢谢啦~

Hibernate入门(八)级联保存或更新(含问题在末尾,求大佬指点..)的更多相关文章

  1. Hibernate入门(九)级联删除

    Hibernate级联删除 上一篇文章学习了级联保存和更新,这个级联删除应该很好理解的.一样的道理,删除一方,同时删除有关联的一方. https://www.cnblogs.com/deepSleep ...

  2. hibernate级联保存,更新个人遇到的问题

    在级联更新的时候,数据库中的数据是增加的,只是外键不存在,导致这样的问题产生的原因是,字表主键ID没有添加到集合中,导致Hibernate找不到子项而执行更新.

  3. hibernate 一对多 级联 保存修改 删除

    一对多,一端设置: <set name="TWorkorderHistories" inverse="true" cascade="all&qu ...

  4. [原创]关于Hibernate中的级联操作以及懒加载

    Hibernate: 级联操作 一.简单的介绍 cascade和inverse (Employee – Department) Casade用来说明当对主对象进行某种操作时是否对其关联的从对象也作类似 ...

  5. (原创)Hibernate 使用过程中(尤其是多对多关联中的级联保存和级联删除)的注意事项(基于项目的总结)

    一.先上知识点: 1.hibernate多对多关联关系中最重要的参数是(基于配置文件xxx.hbm.xml文件形式): 1):inverse属性,如果设置inverse=“true”就代表让对方参与维 ...

  6. Hibernate中表与表之间的关联多对多,级联保存,级联删除

    第一步:创建两个实体类:用户和角色实体类,多对多关系,并让两个实体类之间互相关联: 用户实体类: package com.yinfu.entity; import java.util.HashSet; ...

  7. Hibernate中表与表之间的关联一对多,级联保存和级联删除

    1:Hibernate的一对多操作(重点) 一对多映射配置 第一步:创建两个实体类:客户和联系人(例)以客户为一,联系人为多: package com.yinfu.entity; public cla ...

  8. Hibernate的级联保存、级联删除

    级联操作: 属性:cascade 值:save-update(级联保存) delete(级联删除) all(级联保存+级联删除) 优点:虽然,不用级联操作也能解决问题.但是级联操作可以减少代码量,使得 ...

  9. Hibernate入门5持久化对象关系和批量处理技术

    Hibernate入门5持久化对象关系和批量处理技术 20131128 代码下载 链接: http://pan.baidu.com/s/1Ccuup 密码: vqlv 前言: 前面学习了Hiberna ...

随机推荐

  1. day_8文件的操作

    首先昨天讲的内容有 类型转换 1:数字类型: int ()  bool()  float() 2:str 与int:    int('10') | int('-10') | int('0') | fl ...

  2. 记一个centos分区大小调整过程

    1. 备份 /home 目录 [root@centos ~]# cp -r /home /home_backup 2. 查看目前磁盘使用的情况, 需要将 /dev/mapper/centos-home ...

  3. 架构(四)Git简介,安装以及相关命令SourceTree

    一 Git介绍 1.1 Git是什么? Git是一个分布式版本控制软件: 版本控制:假如开发人员开发了一个a功能,结果项目经理觉得不够需要修改,开发人员又改成了b功能,后来又改成了c功能,但是最终项目 ...

  4. [转]Virtualization Basics

    Virtualization Basics Virtualization is not a new concept, but its complexity has been growing, and ...

  5. Windows 系统中的 CMD 黑窗口简单介绍

    简介 DOS是磁盘操作系统的缩写,是个人计算机上的一类操作系统DOS命令,是DOS操作系统的命令,是一种面向磁盘的操作命令,主要包括目录操作类命令.磁盘操作类命令.文件操作类命令和其它命令.DOS系统 ...

  6. 《http权威指南》读书笔记12

    概述 最近对http很感兴趣,于是开始看<http权威指南>.别人都说这本书有点老了,而且内容太多.我个人觉得这本书写的太好了,非常长知识,让你知道关于http的很多概念,不仅告诉你怎么做 ...

  7. Metasploit Framework(6)客户端渗透(上)

    文章的格式也许不是很好看,也没有什么合理的顺序 完全是想到什么写一些什么,但各个方面都涵盖到了 能耐下心看的朋友欢迎一起学习,大牛和杠精们请绕道 前五篇文章讲解了Metasploit Framewor ...

  8. Spring详解(八)------事务管理

    PS:本篇博客源码下载链接:http://pan.baidu.com/s/1mi3NhX2 密码:3io2 1.事务介绍 事务(Transaction),一般是指要做的或所做的事情.在计算机术语中是指 ...

  9. AI - 框架(Frameworks)

    1 - Scikit-Learn Sklearn(scikit-learn: machine learning in Python):https://scikit-learn.org/ 文档丰富而又详 ...

  10. 树莓派MQTT客户端搭建

    树莓派安装和实现MQTT协议 下载Mosquitto 更新软件源:sudo apt-get  update 下载g++编译器:sudo apt-get install g++ 安装:sudo apt- ...