级联保存或更新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. Openvswitch手册(9): Flow

    这一节我们将flow table flow table主要由ovs-ofctl命令操作 ovs-ofctl可以走和openflow controller一样的协议: ssl:ip[:port]: Th ...

  2. FFmpeg 学习(三):将 FFmpeg 移植到 Android平台

    首先需要去FFmpeg的官网http://www.ffmpeg.org/去下载FFmpeg的源码,目前的版本号为FFmpeg3.3(Hilbert). 下载的文件为压缩包,解压后得到ffmpeg-3. ...

  3. MyBatis 的 XML 映射文件使用说明

    简介 文档参考地址:http://www.mybatis.org/mybatis-3/zh/index.html MyBatis 的真正强大在于它的映射语句,也是它的魔力所在.由于它的异常强大,映射器 ...

  4. 第77节:Java中的事务和数据库连接池和DBUtiles

    第77节:Java中的事务和数据库连接池和DBUtiles 前言 看哭你,字数:8803,承蒙关照,谢谢朋友点赞! 事务 Transaction事务,什么是事务,事务是包含一组操作,这组操作里面包含许 ...

  5. IDEA新手使用教程(详解)

    IDEA从下载安装到使用,手把手教你 一.IDEA的下载 IDEA下载地址:https://www.jetbrains.com/idea/download/#section=windows IDEA ...

  6. HashMap 和 Hashtable 的 6 个区别,最后一个没几个人知道!

    HashMap 和 Hashtable 是 Java 开发程序员必须要掌握的,也是在各种 Java 面试场合中必须会问到的. 但你对这两者的区别了解有多少呢? 现在,栈长我给大家总结一下,或许有你不明 ...

  7. Python编程Day4——if判断、while循环、for循环

    一.if判断 语法一: if条件: 代码块1 代码块2 代码块3 示例: sex='female' age=18 is_beautiful=True if sex =='female'and age& ...

  8. 解决svn图标不显示(绝对有用)

    经常遇到svn图标不显示的问题,然后经过长时间的查找终于找到了一个最最管用的办法,在这里分享给的大家

  9. sql server 索引阐述系列八 统计信息

    一.概述 sql server在快速查询值时只有索引还不够,还需要知道操作要处理的数据量有多少,从而估算出复杂度,选择一个代价小的执行计划,这样sql server就知道了数据的分布情况.索引的统计值 ...

  10. [NewLife.XCode]数据层缓存(网站性能翻10倍)

    NewLife.XCode是一个有10多年历史的开源数据中间件,支持nfx/netcore,由新生命团队(2002~2019)开发完成并维护至今,以下简称XCode. 整个系列教程会大量结合示例代码和 ...