级联保存或更新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. Javascript高级编程学习笔记(63)—— 事件(7)鼠标及滚轮事件

    鼠标与滚轮事件 鼠标事件是web开发中最常用的一类事件,毕竟鼠标是最主要的定位设备 DOM3级事件中定义了9个鼠标事件: click:在用户单击主鼠标按钮(一般为鼠标左键)或者按下回车时触发,这一点对 ...

  2. Java 实现文件压缩工具类

    package com.wdxc.util; import java.io.BufferedInputStream; import java.io.File; import java.io.FileI ...

  3. css3动画:transition和animation

    概述 之前写过css3 动画与display:none冲突的解决方案,但是最近却发现,使用animation效果比transition好得多,而且不和display:none冲突.下面我把相关新的记录 ...

  4. CSS3——:nth-child选择器基本用法简述

    注:n 是从1开始的 :nth-child 是 CSS3 提供的一个好用的选择器,因为在项目中经常用到,所以简单总结了它的常用方法 下面示例代码截图用的是同一个例子,p元素的父元素都是body   p ...

  5. ubuntu下opencv的版本切换及遇到的问题解决

    默认使用opencv 3.2的时候,使用SVM的时候,系统报错如下: error: ‘class MySVM’ has no member named ‘decision_func’ 解决方法:要把系 ...

  6. Python - 一些值得阅读的PEP

    1- PEP简介 PEP是Python增强提案(Python Enhancement Proposal)的缩写.社区通过PEP来给Python语言建言献策,每个版本的新特性和变化都是通过PEP提案经过 ...

  7. MYSQL服务器系统变量

    一:查看服务所有变量 MySQL服务器维护许多配置其操作的系统变量.每个系统变量都有一个默认值.可以使用命令行或选项文件中的选项在服务器启动时设置系统变量.其中大多数都可以在运行时使用动态更改 SET ...

  8. vue项目中主要文件的加载顺序(index.html、App.vue、main.js)

    先后顺序: index.html > App.vue的export外的js代码 > main.js > App.vue的export里面的js代码 > Index.vue的ex ...

  9. 记录js new Date日期处理的一个坑

    记录js日期处理的一个坑   当前时区为北美东部时区时, new Date('2019-4-1') new Date('2019-04-01') 结果是相关一个月的. 如下图   new Date(' ...

  10. python 安装numpy遇到无法卸载的解决办法

    python 安装模块numpy遇到无法卸载的情况的解决办法 python在安装seaborn的时候,需要更新numpy模块,但是更新失败,输出下面的错误: Cannot uninstall 'num ...