Hibernate入门(八)级联保存或更新(含问题在末尾,求大佬指点..)
级联保存或更新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入门(八)级联保存或更新(含问题在末尾,求大佬指点..)的更多相关文章
- Hibernate入门(九)级联删除
Hibernate级联删除 上一篇文章学习了级联保存和更新,这个级联删除应该很好理解的.一样的道理,删除一方,同时删除有关联的一方. https://www.cnblogs.com/deepSleep ...
- hibernate级联保存,更新个人遇到的问题
在级联更新的时候,数据库中的数据是增加的,只是外键不存在,导致这样的问题产生的原因是,字表主键ID没有添加到集合中,导致Hibernate找不到子项而执行更新.
- hibernate 一对多 级联 保存修改 删除
一对多,一端设置: <set name="TWorkorderHistories" inverse="true" cascade="all&qu ...
- [原创]关于Hibernate中的级联操作以及懒加载
Hibernate: 级联操作 一.简单的介绍 cascade和inverse (Employee – Department) Casade用来说明当对主对象进行某种操作时是否对其关联的从对象也作类似 ...
- (原创)Hibernate 使用过程中(尤其是多对多关联中的级联保存和级联删除)的注意事项(基于项目的总结)
一.先上知识点: 1.hibernate多对多关联关系中最重要的参数是(基于配置文件xxx.hbm.xml文件形式): 1):inverse属性,如果设置inverse=“true”就代表让对方参与维 ...
- Hibernate中表与表之间的关联多对多,级联保存,级联删除
第一步:创建两个实体类:用户和角色实体类,多对多关系,并让两个实体类之间互相关联: 用户实体类: package com.yinfu.entity; import java.util.HashSet; ...
- Hibernate中表与表之间的关联一对多,级联保存和级联删除
1:Hibernate的一对多操作(重点) 一对多映射配置 第一步:创建两个实体类:客户和联系人(例)以客户为一,联系人为多: package com.yinfu.entity; public cla ...
- Hibernate的级联保存、级联删除
级联操作: 属性:cascade 值:save-update(级联保存) delete(级联删除) all(级联保存+级联删除) 优点:虽然,不用级联操作也能解决问题.但是级联操作可以减少代码量,使得 ...
- Hibernate入门5持久化对象关系和批量处理技术
Hibernate入门5持久化对象关系和批量处理技术 20131128 代码下载 链接: http://pan.baidu.com/s/1Ccuup 密码: vqlv 前言: 前面学习了Hiberna ...
随机推荐
- 1.1.1 PROB Your Ride Is Here
=== /* ID: luopengting PROG: ride LANG: C++ */ #include <iostream> #include <cstdio> #in ...
- JavaScript的文档对象模型DOM
小伙伴们之前我们讲过很多JavaScript的很多知识点,可以点击回顾一下: <JavaScript大厦之JS运算符>: <JavaScript工作原理:内存管理 + 如何处理4个常 ...
- FFmpeg开发实战(二):FFmpeg 文件操作
FFmpeg 提供了丰富的API供我们使用,下面我们来讲述一下文件操作相关的API: FFmpeg 删除文件:avpriv_io_delete() FFmpeg 重命名文件:avpriv_io_mov ...
- Spring Boot(八):RabbitMQ 详解
RabbitMQ 即一个消息队列,主要是用来实现应用程序的异步和解耦,同时也能起到消息缓冲,消息分发的作用. 消息中间件在互联网公司的使用中越来越多,刚才还看到新闻阿里将 RocketMQ 捐献给了 ...
- 微信公众平台开发——为何不能在网页调用微信jsapi?
说到这问题,相信大部分程序员老手都会轻蔑一笑,当然是跨域导致的啊!但是为了一些小白,我觉得还是很有必要再说一次的. 首先介绍什么是跨域,由于浏览器的同源策略,出于防范跨站脚本的攻击,禁止客户端脚本( ...
- python 分享一个通过 (key1.key2.key3) 形式获取嵌套字典值的方法
最近在做接口自动化测试,响应的内容大多数是多层嵌套的json数据,如果一层层的去剥,效率不高,脚本繁重,所以写了一个可以通过(key1.key2.key3)形式获取嵌套字典值的方法,如有不对或者需要优 ...
- TCP/IP 笔记 - TCP数据流和窗口管理
TCP流量控制机制通过动态调整窗口大小来控制发送端的操作,确保路由器/接收端消息不会溢出. 交互式TCP连接 交互式TCP连接指该连接需要在客户端和服务器之间传输用户输入信息,如按键操作.短消息.操作 ...
- Linux命令行文本工具
浏览文件 cat 查看文件内容 more 以翻页形式查看文件内容(只能向下翻页) less 以翻页形式查看文件内容(可以上下翻页) head 查看文件的头几行(默认10行) tail 查看文件的尾几行 ...
- solr(六): 集群
前言 随着用户的增多,空间和并发量越来越多,会导致一台solr服务器干不过了.这时候,就需要将solr集群以下. 集群架构 由多台服务器共同完成索引和搜索任务 实现的思路是将索引数据进行shard(分 ...
- Zookeeper Client简介
直接使用zk的api实现业务功能比较繁琐.因为要处理session loss,session expire等异常,在发生这些异常后进行重连.又因为ZK的watcher是一次性的,如果要基于wather ...