spring嵌套事务,try-catch事务处理

2023-11-11

spring 事务总结

前置条件

表Teacher 别名 A ,表Student 别名 B 分别插入。

A中启动事务,B中不启动事务 testDemo01调用方法开启事务

testDemo01开启事务,A中insert中开启事务,调用执行,A中执行成功,B中执行出现异常,AB事务回滚。

//A 表处理   
		@Override
    @Transactional
    public int insert(Teacher record) {

        log.info("teacher 插入开始....");
        return teacherDAO.insert(record);
    }
//B表处理
 		@Override
    public int insert(Student record) {
        log.info("Student 插入处理....");
        return studentDAO.insert(record);
    }
//调用方法处理
    @Transactional
    public void testDemo01() throws Exception{

        teacherService.insert(getTeacherEntity(2));
        studentService.insert(getStudentEntity(2));
    }

A,B调用顺序调整。testDemo01开启事务,A中insert中开启事务,调用执行,A中执行异常,B中执行成功,AB事务回滚。

 @Transactional
    public void testDemo01() throws Exception{

        studentService.insert(getStudentEntity(2));
        teacherService.insert(getTeacherEntity(2));

    }
//A
@Override
    @Transactional
    public int insert(Teacher record) {

        log.info("teacher 插入开始....");
        int ss = teacherDAO.insert(record);
        int i = 1 / 0;
        return ss;
    }

A中事务开启新事务,调用后A调用异常,B中正常,A事务回滚,B事务不回滚

//A
@Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public int insert(Teacher record) throws Exception{

        log.info("teacher 插入开始....");
        int ss = teacherDAO.insert(record);
        int i = 1 / 0;
        return ss;
    }

A中开启事务,并使用try catch 将异常抓取。结果 A插入成功,B插入成功。事务没有执行会滚。

//调用方法
@Transactional
    public void testDemo01() throws Exception{

        studentService.insert(getStudentEntity(2));
        teacherService.insert(getTeacherEntity(2));

    }
//A
		@Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public int insert(Teacher record) throws Exception{

        log.info("teacher 插入开始....");
        int ss = 0;
        try{
            ss = teacherDAO.insert(record);
            int i = 1 / 0;
        }catch (Exception e){
            log.error(e.getMessage());
        }

        return ss;
    }

调用方法使用try catch 抓取异常。A方法正常抛出异常,事务进行了会滚,也就是student和teacher都进行了会滚。但是报 Transaction rolled back because it has been marked as rollback-only 异常,这个异常简单来讲,就是事务的传播机制导致的,teacher事务默认是用testDemo01调用方法的事务,但是teacher异常抛出的时候,teacher事务被标记成rollback 状态,所以,在调用方法testDemo01中即使使用trycatch捕捉了异常,同样也会做会滚,以为他俩使用的一个事务。

//调用方法
@Transactional
    public void testDemo01() throws Exception{

        try{
            studentService.insert(getStudentEntity(3));
            teacherService.insert(getTeacherEntity(3));
        }catch (Exception e){
            log.error(e.getMessage());
        }

    }
//Teacher方法
@Override
    @Transactional
    public int insert(Teacher record) throws Exception{

        log.info("teacher 插入开始....");
        int ss = teacherDAO.insert(record);
        int i = 1 / 0;
        return ss;
    }

调整teacher的事物传播机制为 (propagation = Propagation.REQUIRES_NEW),然后teacher会回滚,Student不会进行回滚。

 @Transactional
    public void testDemo01() throws Exception{

        try{
            studentService.insert(getStudentEntity(3));
            teacherService.insert(getTeacherEntity(3));
        }catch (Exception e){
            log.error(e.getMessage());
        }

    }
//
 @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public int insert(Teacher record) throws Exception{

        log.info("teacher 插入开始....");
        int ss = teacherDAO.insert(record);
        int i = 1 / 0;
        return ss;
    }

testDemo01方法和Teacher 都使用trycatch 处理,Teacher不抛出异常,testDemo01也不抛出异常,AB不回滚

 @Transactional
    public void testDemo01() throws Exception{

        try{
            studentService.insert(getStudentEntity(4));
            teacherService.insert(getTeacherEntity(3));
        }catch (Exception e){
            log.error(e.getMessage());
        }

    }
//
 @Override
    @Transactional
    public int insert(Teacher record) throws Exception{

        log.info("teacher 插入开始....");
        int ss = 0;
        try {
            ss = teacherDAO.insert(record);
            int i = 1 / 0;
        } catch (Exception e) {
            log.error(e.getMessage());
        }

        return ss;
    }

testDemo01方法和Teacher 都使用trycatch 处理,Teacher修改事物隔离级别,不抛出异常,testDemo01也不抛出异常,AB不回滚

@Transactional
    public void testDemo01() throws Exception{

        try{
            studentService.insert(getStudentEntity(5));
            teacherService.insert(getTeacherEntity(4));
        }catch (Exception e){
            log.error(e.getMessage());
        }

    }
//
@Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public int insert(Teacher record) throws Exception{

        log.info("teacher 插入开始....");
        int ss = 0;
        try {
            ss = teacherDAO.insert(record);
            int i = 1 / 0;
        } catch (Exception e) {
            log.error(e.getMessage());
        }

        return ss;
    }

testDemo01方法和Teacher 都使用trycatch 处理,Teacher抛出异常,testDemo01不抛出异常,AB不回滚

  @Transactional
    public void testDemo01() throws Exception{

        try{
            studentService.insert(getStudentEntity(6));
            teacherService.insert(getTeacherEntity(5));
        }catch (Exception e){
            log.error(e.getMessage());
        }

    }
// @Override
    @Transactional
    public int insert(Teacher record) throws Exception{

        log.info("teacher 插入开始....");
        int ss = 0;
        try {
            ss = teacherDAO.insert(record);
            int i = 1 / 0;
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new Exception(e.getMessage());
        }

        return ss;
    }

testDemo01方法和Teacher 都使用trycatch 处理,Teacher抛出异常,testDemo01抛出异常(不指定那个异常回滚,注意异常要是RuntimeException,不能是其以上的异常,不然会会滚失败,或者指定异常会滚),AB回滚

  @Transactional
    public void testDemo01() throws Exception{

        try{
            studentService.insert(getStudentEntity(8));
            teacherService.insert(getTeacherEntity(7));
        }catch (Exception e){
            log.error(e.getMessage());
            throw new RuntimeException(e.getCause());
        }

    }
//或者指定会滚异常
 @Transactional(rollbackFor = {Exception.class})
    public void testDemo01() throws Exception{

        try{
            studentService.insert(getStudentEntity(8));
            teacherService.insert(getTeacherEntity(7));
        }catch (Exception e){
            log.error(e.getMessage());
            throw new Exception(e.getCause());
        }

    }
//
 @Override
    @Transactional
    public int insert(Teacher record) throws Exception{

        log.info("teacher 插入开始....");
        int ss = 0;
        try {
            ss = teacherDAO.insert(record);
            int i = 1 / 0;
        } catch (Exception e) {
            log.error(e.getMessage());
            throw new Exception(e.getMessage());
        }

        return ss;
    }

如果使用循环的方式处理异常,如何保证每次循环中 testDemo01中student和teacher 同时会滚,同时有不影响下次插入呢,就是,student每新增一条数据,teacher新增三条,他们的事务在一个事务中,每次执行一次遍历 ,AB都新增数据。然而在遍历中,某一次遍历出现异常后,AB都进行会滚,同时不影响上次遍历数据,不能中断遍历。解决办法是在调用方法时,首先要设立事务的传播特性修改成REQUIRES_NEW(开启新的事务,不在归调用者的事务管理,每次遍历的时候都会开启新事务),另外使用trycatch捕获异常后使用手动操作异常时会滚(这样就不会影响下次遍历了)。异常是否抛出对于调用者不影响。

@Transactional
    public void testC() throws Exception{

        for (int i = 1; i <4; i++) {
            try {
                testService.testDemo01(i);
            } catch (Exception e) {
                continue;
            }
        }
    }
//
@Transactional(propagation = Propagation.REQUIRES_NEW,rollbackFor = {Exception.class})
    public void testDemo01(int i) throws Exception{

        try{
            studentService.insert(getStudentEntity(i));
            teacherService.insert(getTeacherEntity(i));
        }catch (Exception e){
            log.error(e.getMessage());
     		//手动回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            throw new Exception(e.getCause());
        }

    }
//
  @Override
    @Transactional
    public int insert(Teacher record) throws Exception{

        log.info("teacher 插入开始....");
        int ss = 0;
        try {
            int k= record.getId();
            for (int i = 1; i < 3; i++) {

                if (k==1){
                    record.setId(1+i);
                }
                if (k==2){
                    record.setId(3+i);
                }
                if (k==3){
                    record.setId(6+i);
                }
                ss = teacherDAO.insert(record);

                if (k==2){
                    int t = 1 / 0;
                }
            }

        } catch (Exception e) {
            log.error(e.getMessage());
            throw new Exception(e.getMessage());
        }

        return ss;
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

spring嵌套事务,try-catch事务处理 的相关文章

随机推荐

  • ajax内置对象有什么,用js内置对象XMLHttpRequest 来用ajax

    步骤 用XMLHTTPRequest来进行ajax异步数据交交互 主要有几个步骤 1 创建XMLHTTPRequest对象 最复杂的一步 if window XMLHttpRequest code for IE7 Firefox Chrom
  • Apache Beam程序向导4

    今天在集群上实验Beam On Spark的时候 遇到一个坑爹的问题 这个问题总结起来是一个java lang NoClassDefFoundError 错误 具体错误如下图1所示 图1 错误提示 该错误提示SparkStreamingCo
  • cesium中定位方法使用

    cesium中定位到位置 在cesium中viewer flyTo和Camera flyTo的区别挺大 我们通常会用camera来定位 但当需要加上一个倾斜角的时候 可能定位的结果就和预想的区别很大 需求 矩形的中心点位置 110 0 35
  • CSDN竞赛第35期题解

    CSDN竞赛第35期题解 1 题目名称 交换后的or 给定两组长度为n的二进制串 请问有多少种方法在第一个串中交换两个不同位置上的数字 使得这两个二进制串 或 的 结果发生改变 int n cin gt gt n string a b ci
  • Python GUI 设计(三)---Widget组件详解

    1 1 Canvas画布组件 Tkinter模块中的Canvas组件主要用于绘制图形 文字 设计动画等甚至也可以将其他小部件放在画布上 比如视频 它的语法格式如下 Canvas 父窗口 options 第一个参数是父窗口 表示这个画布建立在
  • Linux操作系统~必考面试题⑥

    文件管理命令 1 cat 命令 cat 命令用于连接文件并打印到标准输出设备上 cat 主要有三大功能 1 一次显示整个文件 cat filename 2 从键盘创建一个文件 cat gt filename 3 将几个文件合并为一个文件 c
  • 链表-哈希表 详解

    链表 链表是由一系列节点组成的元素集合 每个节点包含两部分 数据域item和指向一下个节点的指针next 通过节点之间相互连接 最终串联成一个链表 链式存储结构就是 两个相邻的元素在内存中可能不是相邻的 每一个元素都有一个指针域 指针域一般
  • odoo权限管理详解

    前言 odoo作为ERP框架 必然有不同角色的用户使用这同一系统 对于系统上面的数据 应该对不同角色设置不同的查阅修改权限 odoo框架自带了了比较完善的权限控制机制 这篇博客的实践基于odoo13 其他版本可能略有差别 A 按odoo使用
  • 文举论金:黄金原油全面走势分析策略指导。

    市场没有绝对 涨跌没有定势 所以 对市场行情的涨跌平衡判断就是你的制胜法宝 欲望 有句意大利谚语 让金钱成为我们忠心耿耿的仆人 否则 它就会成为一个专横跋扈的主人 空头 多头都能赚钱 唯有贪心不能赚 是你掌控欲望还是欲望掌控你 古人云 不积
  • MVCC 实现原理

    这里是CS大白话专场 让枯燥的学习变得有趣 没有对象不要怕 我们new一个出来 每天对ta说不尽情话 好记性不如烂键盘 自己总结不如收藏别人 在讲解 MVCC 之前先来看一下 MySQL 中事务的四种隔离级别 读未提交 一个事务可以读到另一
  • ChatGPT生成内容很难脱离标准化,不建议用来写留学文书

    ChatGPT无疑是23年留学届的热门话题 也成为了不少留学生再也离不开的万能工具 从总结文献 润色论文 给教授写email似乎无所不能 各大高校对于学生使用ChatGPT的态度也有所不同 例如 哈佛大学教育代理院长 Anne Harrin
  • Unity游戏编程-——迷宫巡逻兵

    文章目录 游戏设计要求 程序设计要求 基本思路分析 模式基础 架构设计 关键模块 遇到的问题 资源地址 游戏设计要求 创建一个地图和若干巡逻兵 使用动画 每个巡逻兵走一个3 5个边的凸多边型 位置数据是相对地址 即每次确定下一个目标位置 用
  • 字节跳动(飞书)产品测试实习生一面

    下面面试问题的顺序记不清了 所以没按面试官问的顺序写 1 性能测试 2 黑盒和白盒 3 用过飞书吗 知道飞书的产品流程吗 4 谈谈你简历上写的项目 提到购物车功能 仔细讲讲 5 学过软件工程管理 说说整个软件的项目管理流程 6 看有服役的经
  • Linux系统调用指南

    Linux系统调用指南 文章是转载 但是我在后面的案例加了不少注解并debug了 如有疑问 留言交流 其实我也不懂 原文链接 blog packagecloud io https zcfy cc article the definitive
  • QTcpSocket发送数据和自定义数据

    在网络应用中 有时候我们会遇到这样的问题 用TCP不断的接收和发送不同类型的数据 数据大小 格式都不相同 起初看了qt的例子 按照例子写的程序效果相当的不好 尤其是在连续发送大数据的时候 接收端根本无法判断数据是否完整了 也不知道什么时候取
  • 基于VMD-LSTM-IOWA-RBF的碳排放混合预测研究(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码实现 1 概述 二氧化碳排放力争于2030年前达到峰值 努
  • uni-app checkbox全选的实现

    界面是这样的 需求 点击全选按钮上述全部选中 再次点击全部取消 解决方案 在js的data里面定义一个allCheck data return allCheck false 上面商品的的checkbox都一样的配置
  • window 无法访问docker_无法在windows中访问docker端口

    我在dockerfile中写了脚本来运行我的角度项目 It将创建集装箱 什么时候我正在运行我的容器我无法在浏览器中访问主机和端口 它说连接被拒绝了 我用windows机器 用工具箱运行docker 我的容器 gt 81471a6fbd35
  • php爬虫简单入门

    前些日子有点空闲就做了一个简单的爬虫 爬取了知乎50W条数据 因为知乎有测试流量过大 导致经常有验证码 本人图片验证码没有研究所以每次都是手动输入 有兴趣的小伙伴可以做个自动识别验证码就可以无限采取了 爬虫使用了curl public fu
  • spring嵌套事务,try-catch事务处理

    spring 事务总结 前置条件 表Teacher 别名 A 表Student 别名 B 分别插入 A中启动事务 B中不启动事务 testDemo01调用方法开启事务 testDemo01开启事务 A中insert中开启事务 调用执行 A中