Spring中@Transactional注解与事务传播机制

文章目录

  • 事务传播机制
  • 事务失效的场景

事务传播机制

事务的传播特性指的是 当一个事务方法调用另一个事务方法时,事务方法应该如何执行。

事务传播行为类型外部不存在事务外部存在事务使用方式
REQUIRED(默认)开启新的事务融合到外部事务中@Transactional(propagation = Propagation.REQUIRED)适用于增删改查
PROPAGATION_SUPPORTS不开启新的事务融合到外部事务中@Transactional(propagation = Propagation.SUPPORTS)适用于查
REQUIRES_NEW开启新的事务不用外部事务,开启新的事务@Transactional(propagation = Propagation.REQUIRES_NEW)适用于内部事务和外部事务不存在业务关联的情况,如记录日志
NOT_SUPPORTED不开启新的事务不用外部事务@Transactional(propagation = Propagation.NOT_SUPPORTED)不常用
NEVER不开启新的事务抛出异常@Transactional(propagation = Propagation.NEVER)不常用
MANDATORY抛出异常融合到外部事务中@Transactional(propagation = Propagation.MANDATORY)不常用
NESTED开启新的事务融合到外部事务中,Savepoint 机制,外层回滚影响内层,内层回滚不影响外层@Transactional(propagation = Propagation.NESTED)不常用

我们平常在 Spring 中使用的注解 @Transactional,不声明 propagation 参数的情况下默认是 REQUIRED 级别。

@Transactional
public void trans() {upsert();query(); // 查log(); // 记录日志
}@Transactional(propagation = Propagation.SUPPORTS) // 外部没有事务时不用开启新的事务
public info query() {}@Transactional(propagation = Propagation.REQUIRES_NEW) // 记录日志和主事务不存在业务关联
public void log() {}

[注意] 从官方文档中可以看出,我们需要区分逻辑事务以及物理事务,在 Propagation.REQUIRES 等级下,尽管每个内部方法都可以区别于外部事务,独立定义 rollback-only 状态,但是内部逻辑事务的状态都会映射到同一个物理事务上,因此内部事务方法的 rollback-only 标志也会影响外部整个事务的 commit.

https://docs.spring.io/spring-framework/reference/data-access/transaction/declarative/tx-propagation.html

事务失效的场景

参考 https://mp.weixin.qq.com/s/m7Pfeq7n9_8s1i4Zoq8qWw

https://www.bilibili.com/video/BV14d4y1r74o/

8 大失效场景:

  1. 方法内的自调用:Spring事务是基于AOP的,只有使用代理对象调用某个方法时,Spring事务才能生效,而在一个方法中调用使用this.xxx 调用方法时,this并不是代理对象,所以会导致事务失效。

    解放办法1:把调用方法拆分到另外一个Bean中

    解决办法2:自己注入自己

    解決办法3:AopContext.currentProxy0+@EnableAspectAutoProxy(exposeProxy = true)

  2. 方法是private的:Spring事务会基于CGLIB来进行AOP,而CGLIB会基于父子类来失效(最终 Spring Bean 调用的是被增强的子类),子类是代理类,父类是被代理类,如果父类中的某个方法是private的,那么子类就没有办法重写它,也就没有办法额外增加Spring事务的逻辑。

  3. 方法是final的:原因和private是一样的,也是由于子类不能重写父类中的final的方法

  4. 单独的线程调用方法:当Mybatis或JdbcTemplate执行SQL时,会从ThreadLocal中去获取数据库连接对象,如果开启事务的线程和执行SQL的线程是同一个,那么就能拿到数据库连接对象,如果不是同一个线程,那就拿到不到数据库连接对象,这样,Mybatis或JdbcTemplate就会自己去新建一个数据库连接用来执行SQL,此数据库连接的autocommit为true,那么执行完SQL就会提交,后续再拋异常也就不能再回滚之前已经提交了的SQL了。

  5. 没加@Configuration注解:如果用SpringBoot基本没有这个问题,但是如果用的Spring,那么可能会有这个问题,这个问题的原因其实也是由于Mybatis或JdbcTemplate会从ThreadLocal中去获取数据库连接,但是ThreadLocal中存储的是一个MAP,MAP的key为Datasource对象,value为连接对象,而如果我们没有在AppConfig上添加@Configuration注解的话,会导致MAP中存的DataSource对象和Mybatis和JdbcTemplate中的DataSource对象不相等,从而也拿不到数据库连接,导致自己去创建数据库连接了。

  6. 异常被吃掉:如果Spring事务没有捕获到异常,那么也就不会回滚了,默认情况下Spring会捕获RuntimeException和Error。

    解释一下上面提到的注意点:外部事务方法 saveUserWithLog 在调用内部事务方法 logService.insertLog 时,虽然捕获了异常,但是内部事务方法有异常抛出时,整个外部事务仍然会回滚并抛出异常 Transaction rolled back because it has been marked as rollback-only,这是因为默认 @Transactional 用的是 REQUIRED 事务传播等级,内部事务方法会融合到外部事务中,内部事务方法出现异常时就会将整个 物理 connection 设置为 rollback-only,所以共用此 connection 的整个外部事务也会回滚。

    @Transactional(rollbackFor = Exception.class)
    public Integer saveUserWithLog() {try {// 默认 @Transactional(propagation = Propagation.REQUIRED) 抛出异常logService.insertLog();} catch (Exception e) {}User user = new User();user.setId(1001);user.setName("jxz_rollback");user.setAge(1);userMapper.insert(user);return user.getId();
    }
    
  7. 类没有被Spring管理

  8. 数据库不支持事务

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/482694.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Matlab Simulink HDL Coder开发流程(一)— 创建HDL兼容的Simulink模型

创建HDL兼容的Simulink模型 一、使用Balnk DUT模板二、从HDL Coder库中选择模块三、为DUT开发算法/功能四、为设计创建Testbench五、仿真验证设计功能六、Simulink模型生成HDL代码 这个例子说明了如何创建一个用于生成HDL代码的Simulink模型。要创建兼容HDL代码生成的MATLAB算法…

如何通过 JWT 来解决登录认证问题

1. 问题引入 在登录功能的实现中 传统思路: 登录页面时把用户名和密码提交给服务器服务器验证用户名和密码,并把检验结果返回给后端如果密码正确,则在服务器端创建 session,通过 cookie 把 session id 返回给浏览器 但是正常情…

像素流送api ue多人访问需要什么显卡服务器

关于像素流送UE推流,在之前的文章里其实小芹和大家聊过很多,不过今天偶然搜索发现还是有很多小伙伴,在搜索像素流送相关的问题,搜索引擎给的提示有这些。当然这些都是比较短的词汇,可能每个人真正遇到的问题和想获取的…

Uniad复现学习

在优云平台部署训练,加速训练。 关于UCloud(优刻得)旗下的compshare算力共享平台 UCloud(优刻得)是中国知名的中立云计算服务商,科创板上市,中国云计算第一股。 UCloud(优刻得)旗下的Compshare算力共享平台具有以下优点…

域名解析系统 DNS

1.域名系统概述 用户与互联网上某台主机通信时,必须要知道对方的IP地址。然而用户很难记住长达32 位的二进制主机地址。即使是点分十进制地址也并不太容易记忆。但在应用层为了便于用户记忆各种网络应用,连接在互联网上的主机不仅有P地址,而…

【软考网工笔记】网络基础理论——网络层

文章目录 中断处理过程数据包组装RIPRSVPipv4RIPv1 & RIPv2HFC 混合光纤同轴电缆(Hybrid Fiber Coax,简称HFC)BGP (边界网关协议)BGP-4 协议的四种报文ICMP 协议数字语音电子邮件协议MPLS 多协议标记交换ipv6DHCPDNS名称解析过程查询顺序…

go语言 Pool实现资源池管理数据库连接资源或其他常用需要共享的资源

go Pool Pool用于展示如何使用有缓冲的通道实现资源池,来管理可以在任意数量的goroutine之间共享及独立使用的资源。这种模式在需要共享一组静态资源的情况(如共享数据库连接或者内存缓冲区)下非 常有用。如果goroutine需要从池里得到这些资…

【Delphi】modbus-TCP 协议库

在日常开发中,也会遇到使用modbus的部件,比如温度控制器、读卡器等等,那么使用Delphi开发,也就必须遵守modbus-TCP协议,如果自己使用TCP控件写也没有问题,不过如果有开源的三方库,别人已经调试过…

【Git 操作】-- 将 fork master 分支的最新commit更新到自己的仓库

目录 1.举例 2. 配置上游仓库(Upstream) 3. 获取上游仓库的更新 4. 切换到你自己的 master 分支 5. 合并上游仓库的 master 分支 6. 解决冲突(如果有的话) 7. 推送更新到你自己的 GitHub 仓库 1.举例 当我们从 github 的 h…

Facebook的开源项目解析:推动开发者社区的技术进步

Facebook,作为全球领先的社交平台之一,其在技术领域的创新不仅体现在产品功能的实现上,也积极推动开源社区的发展。开源项目已经成为Facebook技术战略的重要组成部分,通过开源,Facebook不仅加速了技术进步,…

荣耀300系列革新发布:科技与美学的里程碑之作

2024年12月2日,全新一代荣耀300系列正式发布,新潮的环球旅拍发布会不仅展现了荣耀追求极致的创新理念,也标志着数字系列迎来科技体验以及美学设计的巨大升级。凭借荣耀领先行业的AI能力以及对底层科技创新的强大驱动,全新荣耀300系…

centos 7 离线安装postgis插件

前一段时间记录了下如何在centos7中离线安装postgresql,因为工作需要,我不仅要安装postgresql,还需要安装postgis插件,这篇文章记录下postgis插件的安装过程。 1. 安装前的参考 如下的链接都是官网上的链接,对你安装p…

ChatGPT/AI辅助网络安全运营之-数据解压缩

在网络安全的世界中,经常会遇到各种压缩的数据,比如zip压缩,比如bzip2压缩,gzip压缩,xz压缩,7z压缩等。网络安全运营中需要对这些不同的压缩数据进行解压缩,解读其本意,本文将探索一…

kube-proxy的iptables工作模式分析

系列文章目录 iptables基础知识 文章目录 系列文章目录前言一、kube-proxy介绍1、kube-proxy三种工作模式2、iptables中k8s相关的链 二、kube-proxy的iptables模式剖析1.集群内部通过clusterIP访问到pod的流程1.1.流程分析 2.从外部访问内部service clusterIP后端pod的流程2.1…

【Linux】文件操作的艺术——从基础到精通

🎬 个人主页:谁在夜里看海. 📖 个人专栏:《C系列》《Linux系列》《算法系列》 ⛰️ 道阻且长,行则将至 目录 📚前言:一切皆文件 📚一、C语言的文件接口 📖1.文件打…

AI 声音:数字音频、语音识别、TTS 简介与使用示例

在现代 AI 技术的推动下,声音处理领域取得了巨大进展。从语音识别(ASR)到文本转语音(TTS),再到个性化声音克隆,这些技术已经深入到我们的日常生活中:语音助手、自动字幕生成、语音导…

IDEA连接Apifox客户端

IDEA连接Apifox客户端 一、下载Apifox安装包二、IDEA配置三、配置Apifox和IDEA项目同步 一、下载Apifox安装包 Apifox官网,根据自己的操作系统下载对应的Apifox安装包,我是windows系统所以下载的是windows版。 下载 默认仅为我安装,点击下一…

Vue3 脚手架扩展

当 yarn dev 运行成功后,我们继续添加扩展 首先我们要安装一些依赖 其中的vue-router和vuex安装最新版的就行,因为项目是vue3 element-plus和less,less-loader最好按照我这个版本来下载 element-plus是一个vue常用的ui组件库 element-plus/…

STM32 ADC模数转换器原理及单通道多通道测量电压模板代码

ADC简介: (主要用来测电压) 1us转换时间(最大支持1MHZ的信号转换) 12位(0~4095)就是分辨率 通过ADC0809外挂芯片来理解STM32中的ADC: 地址锁存和译码是用来选择通路的,…

Android矩阵Matrix实现Glide图像fitCenter转换为centerCrop,Kotlin

Android矩阵Matrix实现Glide图像fitCenter转换为centerCrop&#xff0c;Kotlin <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.a…