前言

传统springboot实现事务只需要在方法上添加@Transactional注解,但是需要在所有的service都加上事务,相对比较麻烦,随着项目的庞大,功能模块会随之增多,所以就需要采用AOP的方式实现全局事务处理。
全局事务配置通过AOP切面指定方法前缀切入点,从而对指定的方法统一进行事务控制,根据方法名前缀来匹配到具体方法,进行事务配置

一、什么是事务?

提到事务,你肯定不陌生,和数据库打交道的时候,我们总会用到事务

案例

你要给朋友小王转 100 块钱,而此时你的银行卡只有 100 块钱。转账过程具体到程序里会有一系列的操作,比如查询余额、做加减法、更新余额等,这些操作必
须保证是一体的,不然等程序查完之后,还没做减法之前,你这 100 块钱,完全可以借着这个时间差再查一次,然后再给另外一个朋友转账,如果银行这么整,不就乱了么?这时就要用到 “ 事务 ” 这个概念了。

概念

简单来说,事务就是保证数据操作,要么全部成功,要么全部失败。MySQL 虽然支持多引擎系统,但并不是所有的引擎都支持事务。比如 MySQL 原生的 MyISAM 引擎就不支持事务,这也是 MyISAMInnoDB 取代的重要原因之一。

二、事务的特性(ACID)

  • 原子性(Atomicity):在事务操作中,要么全部成功,要么全部失败。
  • 一致性(Consistency):事务改变前后,状态一致。
  • 隔离性(Isolation):两个事物直接互不干扰。
  • 持久性(Durability):持久到硬盘。

三、隔离性与隔离级别

为什么需要隔离

当数据库上有多个事务同时执行时候,就会出现并发问题:

  • 脏读( dirty read):对于两个事务T1,T2,T1读取了已经被T2更新但还没有被提交的字段之后,若T2回滚,T1读取的内容就是临时且无效的。
  • 不可重复度( non-repeatable read ):对于两个事务T1,T2,T1读取了一个字段,然后T2更新了该字段之后,T1在读取同一个字段,值就不同了。
  • 幻读( phantom read):对于两个事务T1,T2,T1在A表中读取了一个字段,然后T2又在A表中插入了一些新的数据时,T1再读取该表时,就会发现神不知鬼不觉的多出几行了…

为了解决这些问题,就有了 “ 隔离级别 ” 的概念。

隔离级别

重点: 隔离得越严实,效率就会越低。
SQL 标准的事务隔离级别包括:

  • 读未提交( read uncommitted ): 一个事务还没提交时,它做的变更就能被别的事务看到(脏读、不可重复读和幻读的问题都会出现)。
  • 读提交( read committed ): 一个事务提交之后,它做的变更才会被其他事务看到(可以避免脏读,但不可重复读和幻读的问题仍然可能出现)。
  • 可重复读( repeatable read ): 确保事务可以多次从一个字段中读取相同的值,在这个事务持续期间,禁止其他事务对这个字段进行更新(update)。(可以避免脏读和不可重复读,但幻读仍然存在)
  • 串行化( serializable ): 顾名思义是对于同一行记录, “ 写 ” 会加 “ 写锁 ” , “ 读 ” 会加 “ 读锁 ” 。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。

其中 “ 读提交 ” 和 “ 可重复读 ” 比较难理解,所以我用一个例子说明这几种隔离级别。假设数据表 T 中只有一列,其中一行的值为 1 ,下面是按照时间顺序执行两个事务的行为。

mysql> create table T(c int) engine=InnoDB;
insert into T(c) values(1);


在不同的隔离级别下,事务 A 会有哪些不同的返回结果,也就是图里面 V1 、 V2 、 V3 的返回值分别是什么。

  • 若隔离级别是 “ 读未提交 ” , 则 V1 的值就是 2 。这时候事务 B 虽然还没有提交,但是结果已经被 A 看到了。因此, V2 、 V3 也都是 2 。
  • 若隔离级别是 “ 读提交 ” ,则 V1 是 1 , V2 的值是 2 。事务 B 的更新在提交后才能被 A 看到。所以V3 的值也是 2 。
  • 若隔离级别是 “ 可重复读 ” ,则 V1 、 V2 是 1 , V3 是 2 。之所以 V2 还是 1 ,遵循的就是这个要求:事务在执行期间看到的数据前后必须是一致的。
  • 若隔离级别是 “ 串行化 ” ,则在事务 B 执行 “ 将 1 改成 2” 的时候,会被锁住。直到事务 A 提交后,事务 B 才可以继续执行。所以从 A 的角度看, V1 、 V2 值是 1 , V3 的值是 2 。

好了,概念说完了,下面进入主题,SpringBoot 全局事务配置。

四、SpringBoot 全局事务配置

/*** @author lanys* @author Think* @title: SpringTxAspect* @projectName material_cloud* @description: Spring 全局事务切面配置* @date 2022/11/2 12:18*/
@Aspect
@Configuration
public class SpringTxAspect {/** 切面,根据自己的项目定义不同的表达式execution **/private static final String AOP_POINTCUT_EXPRESSION = "execution(* com.material_cloud.short_link.modules.service.impl.*.*(..))";@Resourceprivate PlatformTransactionManager transactionManager;/*** 增强(事务)的属性的配置** @title: txAdvice* @author lanys 2022-11-02* @Description: 配置* @param* @return TransactionInterceptor*/@SuppressWarnings({ "unchecked", "rawtypes" })@Beanpublic TransactionInterceptor txAdvice() {NameMatchTransactionAttributeSource txAttributeS = new NameMatchTransactionAttributeSource();RuleBasedTransactionAttribute requiredAttr = new RuleBasedTransactionAttribute();// PROPAGATION_REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中requiredAttr.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);// 抛出异常后执行切点回滚requiredAttr.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));//RuleBasedTransactionAttribute supportsAttr = new RuleBasedTransactionAttribute();// PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行supportsAttr.setPropagationBehavior(TransactionDefinition.PROPAGATION_SUPPORTS);// 只读事务,不做更新操作supportsAttr.setReadOnly(true);// 注意:方法名称来自类匹配的到方法【save*, “*”表示匹配任意個字符】Map txMethod = new HashMap();txMethod.put("insert*", requiredAttr);txMethod.put("add*", requiredAttr);txMethod.put("update*", requiredAttr);txMethod.put("modify*", requiredAttr);txMethod.put("remove*", requiredAttr);txMethod.put("delete*", requiredAttr);txMethod.put("bind*", requiredAttr);txMethod.put("unbind*", requiredAttr);// readOnly = truetxMethod.put("select*", supportsAttr);txMethod.put("get*", supportsAttr);txMethod.put("find*", supportsAttr);txMethod.put("query*", supportsAttr);txMethod.put("read*", supportsAttr);txMethod.put("check*", supportsAttr);//txAttributeS.setNameMap(txMethod);TransactionInterceptor txAdvice = new TransactionInterceptor(transactionManager, txAttributeS);return txAdvice;}/*** AOP配置定义切面和切点的信息** @title: txAdviceAdvisor* @author lanys 2022-11-02* @Description: AdvisorBean* @return Advisor*/@Beanpublic Advisor txAdviceAdvisor() {AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();pointcut.setExpression(AOP_POINTCUT_EXPRESSION);return new DefaultPointcutAdvisor(pointcut, txAdvice());}
}

SpringBoot 全局事务配置相关推荐

  1. springboot 配置全局响应数据_spring boot 全局事务配置

    我发现很多开源的springBoot项目,使用事务都是 直接使用 事务注解.并没有配置全局事务的. 其实目前现在不是新人程序员就以为 事务就只能靠加注解来控制了.根本没听说过全局事务配置. 网上很多全 ...

  2. 【springboot】配置

    配置文件 SpringBoot使用一个全局的配置文件,配置文件名是固定的: •application.properties •application.yml 配置文件的作用:修改SpringBoot自 ...

  3. SpringBoot自动配置的原理及实现

    SpringBoot的核心就是自动配置,自动配置是基于条件判断配置Bean 自动配置的源码在spring-boot-autoconfigure-2.2.13.RELEASE SpringBoot运行原 ...

  4. 这样讲 SpringBoot 自动配置原理,你应该能明白了吧

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者:你在我家门口 juejin.im/post/5ce5effb ...

  5. SpringBoot之配置嵌入式Servlet容器

    1.概述 文章目录 1.概述 2.如何修改SpringBoot的默认配置 3.定制和修改Servlet容器的相关配置 4.注册Servlet三大组件 5.替换为其他嵌入式Servlet容器 6.嵌入式 ...

  6. springboot中配置了拦截器后,拦截器无效的解决方案之一

    springboot中配置了拦截器后,拦截器无效的解决方案之一 参考文章: (1)springboot中配置了拦截器后,拦截器无效的解决方案之一 (2)https://www.cnblogs.com/ ...

  7. 【Spring框架家族】SpringBoot自动配置基本实现

    SpringBoot自动配置-Condition_1 Condition是Spring4.0后引入的条件化配置接口,通过实现Condition接口可以完成有条件的加载相应的Bean @Conditio ...

  8. springboot起步配置和自动配置原理

    一.起步配置 1.起步配置Ctrl+左键进入 2.springboot自动识别resources目录下以application开头的配置文件 3.spring-boot-starter-parent又 ...

  9. SpringBoot 自动配置

    Springboot 自动配置 关注 "弋凡"(YiFan)微信公众号吧 记录简单笔记 做你的最爱 Springboot 是什么呐? 我管她是什么,好用就行了啊!!! spring ...

最新文章

  1. arduino跑python,尝试在我的Arduino和stu上执行Python3.7.2中的代码
  2. wiki多个文件一起导入_mac文件信息管理工具EagleFiler for Mac分享给大家
  3. Ubuntu SVN安装使用命令
  4. 【Android 应用开发】 FastJson 使用详解
  5. 光猫直连电脑不能上网_电脑插上网线不能上网怎么办
  6. Pycharm切换anaconda的环境
  7. db2 创建样本数据库_db2创建数据库
  8. android蓝牙设计与实现,一个Android客户端的蓝牙支付系统设计与实现
  9. 【Python】import自己的模块报错
  10. java 1是flase_Java这段代码为什么会返回 false?传入的是字符串[1,1]
  11. java分页插件PageHelper的内置list数据操作失败
  12. 在linux centos7上安装git
  13. mysql 事务 select_mysql 多个select需要放入一个事务吗?
  14. 总算完成了第一个项目,宿管系统,和感想
  15. 查找整数的位置c语言,1-1 编程总结:查找整数
  16. vue项目中报常见错误
  17. Tomcat的安装与配置
  18. Redis面试题(2020最新版)
  19. 【LeetCode - 247】中心对称数 II
  20. SQL 完整的实体性—联系图

热门文章

  1. js日历多选(在表单中显示)
  2. GooglePlay马甲包过审详细流程
  3. 原生js或者jquery获取父级元素/同级元素/下级元素
  4. win 7笔记本连接wifi不能输入密码解决办法(图文教程)
  5. FortiGate防火墙GRE隧道监控
  6. CF 868 div2 A—C
  7. 如何让自己像打王者荣耀一样发了疯、拼了命、石乐志的学习?(强烈推荐)
  8. 论文阅读之《Color Constancy Using CNNs》
  9. PhotonServer中日志的配置
  10. Ubuntu下安装Nvidia和Intel双显卡驱动