springboot中使用@Transactional注解事物不生效的坑

作者:张Sir66666 时间:2021-10-03 10:01:47 

一:在springboot中使用事物遇到的坑

1.我们知道spring中的事物分为两种:一种是编程式事物,一种是声明式事物。顾名思义,编程式事物是指通过代码去实现事物管理,这里不做过多说明。另一种是声明式事物,分为两种情况01:一种是通过传统xml方式配置,02:使用@Transaction注解方式配置,这是主要讲解的是通过注解方式配置。因为在springboot项目中,会自动配置DataSourceTransactionManager,我们只需要在对应的方法上或者类上加上@Transaction就会自动接入到spring的事物中,让spring管理。

2.继续踩坑

**01坑:**如下图所示,我这边本地调用接口修改数据库张三口袋里面的金额,并且启用了事物管理,抛出RuntimeExecption。这时我们调用接口,我们可以看到事物生效了,数据库里面值并没有发生改变。但是,当我们把抛出的异常改为
throw new SQLTimeoutException(); 调用接口的时候,发现数据库张三的金额被改变了,事物没起作用,明明开启了事物,但是没起作用,这是为什么呢?

springboot中使用@Transactional注解事物不生效的坑

02坑: 在我们需要执行事物的方法,如果对异常进行抛出,并且我们手动捕获了这个异常的话,这时候事物也不会起作用的。如下图所示:

springboot中使用@Transactional注解事物不生效的坑

03坑:@Transaction注解只对方法名为pubic的才生效,其他事物不会生效。

04坑: 默认情况下,只有来自外部的方法调用才会被AOP代理捕获,也就是,类内部方法调用本类内部的其他方法并不会引起事务行为,即使被调用方法使用@Transactional注解进行修饰。

3.解决方案

01:Spring的事务管理默认是针对Error异常和RuntimeException异常以及其子类进行事务回滚。对runtimeException并不需要抛出,error需要抛出异常,并进行捕获。所以我们上面用到的SQLTimeoutException()并不属于这两者之间,我们需要手动回滚异常,在@Transaction注解里面指定回滚异常类型即可,我这里举一个例子@Transactional(rollbackFor = Exception.class)

02: 我们在需要执行的sercvice里面不应该主动捕获异常,这会导致我们事物不生效,应该继续往上抛,在controller层捕获即可,这样事物也生效了,异常也捕获了。

03:@Transaction注解只对方法名为pubic的才生效,其他事物不会生效。顾名思义,也就是说使用了@Transaction注解的,只能是public。因为只有@Transaction注解只有被其他方法调用才生效的,能被其他方法调用的方法,只能是public。

04:我们在使用事物注解的时候,尽量不要在类上面使用,这会使得类里面的所有方法都会有事物进行处理。比如说,我们一些方法只做查询操作,我们就没有必要再进行事物,我们应该在需要事物处理的方法上面加事物,并且指定回滚的异常类型。

二:既然说到spring的事物了,再说一下spring事物的隔离级别吧

原文 参考文章:https://www.jb51.net/article/204803.htm
Isolation :隔离级别
隔离级别是指若干个并发的事务之间的隔离程度,与我们开发时候主要相关的场景包括:脏读取、重复读、幻读。
我们可以看 org.springframework.transaction.annotation.Isolation 枚举类中定义了五个表示隔离级别的值:


public enum Isolation {
DEFAULT(-1),
READ_UNCOMMITTED(1),
READ_COMMITTED(2),
REPEATABLE_READ(4),
SERIALIZABLE(8);
}

DEFAULT :这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是: READ_COMMITTED 。
READ_UNCOMMITTED :该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读和不可重复读,因此很少使用该隔离级别。
READ_COMMITTED :该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。
REPEATABLE_READ :该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。即使在多次查询之间有新增的数据满足该查询,这些新增的记录也会被忽略。该级别可以防止脏读和不可重复读。
SERIALIZABLE :所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
指定方法:通过使用 isolation 属性设置,例如:@Transactional(isolation = Isolation.DEFAULT)

Propagation:传播行为

所谓事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。

我们可以看 org.springframework.transaction.annotation.Propagation 枚举类中定义了6个表示传播行为的枚举值:


public enum Propagation {
REQUIRED(0),
SUPPORTS(1),
MANDATORY(2),
REQUIRES_NEW(3),
NOT_SUPPORTED(4),
NEVER(5),
NESTED(6);
}

REQUIRED :如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
SUPPORTS :如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
MANDATORY :如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
REQUIRES_NEW :创建一个新的事务,如果当前存在事务,则把当前事务挂起。
NOT_SUPPORTED :以非事务方式运行,如果当前存在事务,则把当前事务挂起。
NEVER :以非事务方式运行,如果当前存在事务,则抛出异常。
NESTED :如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 REQUIRED 。
指定方法:通过使用 propagation 属性设置,例如:@Transactional(propagation = Propagation.REQUIRED)

来源:https://blog.csdn.net/Z__Sheng/article/details/89489053

标签:springboot,@Transactional,不生效
0
投稿

猜你喜欢

  • spring解决循环依赖的方案示例

    2021-11-19 03:31:04
  • java二维数组实现推箱子小游戏

    2022-08-31 10:18:40
  • 详解java中产生死锁的原因及如何避免

    2022-04-22 00:36:14
  • 三道java新手入门面试题,通往自由的道路--多线程

    2023-05-24 23:12:51
  • java堆排序概念原理介绍

    2021-08-30 12:31:58
  • SpringMVC记录我遇到的坑_AOP注解无效,切面不执行的解决

    2021-08-09 06:20:58
  • Hadoop+HBase+ZooKeeper分布式集群环境搭建步骤

    2022-02-13 01:16:33
  • Java异常处理try catch的基本用法

    2022-11-27 11:36:15
  • Android 通过SQLite数据库实现数据存储管理

    2023-09-28 11:31:59
  • 25行Java代码将普通图片转换为字符画图片和文本的实现

    2023-11-24 02:04:26
  • Java实现读写文件功能的代码分享

    2023-02-07 04:07:02
  • Jenkins节点配置实现原理及过程解析

    2023-02-14 11:53:30
  • 详解java操作Redis数据库的redis工具(RedisUtil,jedis工具JedisUtil,JedisPoolUtil)

    2023-07-29 11:31:36
  • java实现轻量型http代理服务器示例

    2021-10-05 18:14:20
  • 详解Java分布式事务的 6 种解决方案

    2022-06-19 13:33:49
  • JavaSE实现猜拳游戏

    2023-12-22 07:21:19
  • 深入理解Java责任链模式实现灵活的请求处理流程

    2022-06-06 23:33:53
  • Java实现图片倒影的源码实例内容

    2022-08-30 02:39:24
  • 使用@PropertySource读取配置文件通过@Value进行参数注入

    2021-11-21 13:21:03
  • 详解Java并发包中线程池ThreadPoolExecutor

    2022-03-23 19:57:20
  • asp之家 软件编程 m.aspxhome.com