IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 解决Spring子事务新开事务REQUIRES_NEW仍被主事务回滚问题 -> 正文阅读

[Java知识库]解决Spring子事务新开事务REQUIRES_NEW仍被主事务回滚问题

解决子事务新开事务被主事务回滚问题

Spring提供的事务传播机制:

1.REQUIRED (默认):支持当前事务,如果当前没有事务,则新建事务,如果当前存在事务,则加入当前事务,合并成一个事务,如果一个方法发生异常回滚,则整个事务回滚。

2.REQUIRES_NEW:新建事务,如果当前存在事务,则把当前事务挂起,这个方法会独立提交事务,不受调用者的事务影响,父级异常,它也是正常提交,但如果是此方法发生异常未被捕获处理,且异常满足父级事务方法回滚规则,则父级方法事务会被回滚。

问题:

现有如下处理逻辑:

从消息队列中读取消息开始配置设备信息-> 设备信息入表,预占资源 -> 发生异常时在catch代码块中的处理逻辑如下:

catch (Exception e) {
            log.info(orderId + "自动配端口失败:{}", e);
            try {
                autoToErr(orderId + "配置出现异常,转手工配置");
            } catch (Exception exception) {
                throw exception;
            }
         }
     }

核心操作在于:

autoToErr(orderId + "配置出现异常,转手工配置");

表示自动配置失败,将配置失败的订单信息存入err表,记录下来用于转手工配置

但是产生了如下问题:

  • 当未开启事务时,如果发生异常,记录err表成功,但是设备信息已入表,资源已被预占无法释放!

针对上述问题,在方法上开启注解,并在发生异常时回滚

@Transactional(rollbackFor = Exception.class)
public JSONObject autoAssignSplitter(String orderId) throws Exception {
    ...
        try {
            ...
        } catch(...) {
            autoToErr(orderId + "配置出现异常,转手工配置");
        }
    ...
}

但是会出现,处理失败后,预占资源被释放,但是插入err表的操作也被回滚掉

所以根据上述事务传播机制,在aotoToManualAssign方法上声明其事务传播机制为REQUIRES_NEW

// 新建事务,不受调用该事务的父事务回滚影响
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public void autoToErr(String failMsg) 
    throws Exception {
    ...
}
  • 但是又发生了新问题:声明的事务传播机制没有生效,还是全部回滚

原因分析:
在这里插入图片描述

打印发现:父事务和子事务的调用对象不是同一个代理对象,这就是为什么添加REQUIRES_NEW不起作用,想要让注解生效就要用代理对象的方法。

所以我们需要把代理对象暴露出来,并使用其来调用子事务,来保证结果正确性

最终实现的代码:

  1. 使用@EnableAspectJAutoProxy,并将exposeProxy设置为true,默认为false

    public @interface EnableAspectJAutoProxy {
        boolean proxyTargetClass() default false;
    
        boolean exposeProxy() default false;
    }
    
@EnableAspectJAutoProxy(exposeProxy = true,proxyTargetClass = true)
public class ConfigController {
	...
}
  1. 在子事务调用时使用代理对象:
((ConfigPortBiz)AopContext.currentProxy()).autoToErr(orderId + "配置出现异常,转手工配置");
  1. 将子事务传播机制声明为REQUIRES_NEW
// 新建事务,不受调用该事务的父事务回滚影响
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public void autoToErr(String failMsg) 
    throws Exception {
    ...
}
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-09-15 01:51:23  更:2022-09-15 01:53:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:00:20-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码