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

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

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

2.继续踩坑

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

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

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)

到此这篇关于springboot中使用@Transactional注解事物不生效的原因的文章就介绍到这了,更多相关springboot @Transactional不生效内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • springboot中事务管理@Transactional的注意事项与使用场景

    前言:在service层的方法上使用@Transactional 即可实现处理数据库发生错误时触发事务回滚机制. 注意: Spring 基于注解的声明式事物 @Transactional 默认情况下只会对运行期异常(java.lang.RuntimeException及其子类)和 Error 进行回滚. 数据库引擎要支持事物,使用InnoDB. @Transactional 只能被应用到public方法上, 对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没

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

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

  • 解决SpringBoot中使用@Transactional注解遇到的问题

    目录 使用@Transactional注解遇到的问题 1.不建议在接口上添加@Transactional注解 2.@Transactional注解 3.默认情况下 4.数据库引擎需要支持事务管理 5.同一类中methodA()方法 springboot 注解transactional失效 1.在方法中捕获了异常 2.spring中事务是代理模式 3.A方法如果有事务注解 4.本类中A方法调用 使用@Transactional注解遇到的问题 1.不建议在接口上添加@Transactional注解

  • 解决SpringBoot中使用@Async注解失效的问题

    错误示例,同一个类中使用异步方法: package com.xqnode.learning.controller; import com.fasterxml.jackson.core.JsonProcessingException; import org.springframework.scheduling.annotation.Async; import org.springframework.web.bind.annotation.GetMapping; import org.springf

  • SpringBoot中使用@Scheduled注解创建定时任务的实现

    在项目日常开发过程中,经常需要定时任务来帮我们做一些工作,如清理日志.定时任务的实现方法主要有 Timer.Quartz 以及 elastic-job Timer 实现定时任务 只执行一次的定时任务 Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { System.out.println("2000毫米后执行一次."); } }, 2000); timer.s

  • 详解SpringBoot中添加@ResponseBody注解会发生什么

    SpringBoot版本2.2.4.RELEASE. [1]SpringBoot接收到请求 ① springboot接收到一个请求返回json格式的列表,方法参数为JSONObject 格式,使用了注解@RequestBody 为什么这里要说明返回格式.方法参数.参数注解?因为方法参数与参数注解会影响你使用不同的参数解析器与后置处理器!通常使用WebDataBinder进行参数数据绑定结果也不同. 将要调用的目标方法如下: @ApiOperation(value="分页查询") @Re

  • 详解SpringBoot中@NotNull,@NotBlank注解使用

    目录 一.添加依赖 二.在类中使用验证注解 1.创建验证实体类(嵌套使用) 2.创建全局异常处理器,对message信息进行处理,并返回给前端 3.在controller中的使用 三.在方法参数中使用验证注解,与@RequsetParam注解同时使用,注意类上使用@Validated 四.自定义验证注解 一.添加依赖 <!-- spring-boot 2.3及以上的版本只需要引入下面的依赖 --> <dependency> <groupId>org.springfram

  • 浅谈SpringBoot中的@Conditional注解的使用

    概述 Spring boot 中的 @Conditional 注解是一个不太常用到的注解,但确实非常的有用,我们知道 Spring Boot 是根据配置文件中的内容,决定是否创建 bean,以及如何创建 bean 到 Spring 容器中,而 Spring boot 自动化配置的核心控制,就是 @Conditional 注解. @Conditional 注解是 Spring 4.0 之后出的一个注解,与其搭配的一个接口是 Condition,@Conditional 注解会根据具体的条件决定是否

  • SpringBoot中的@Value注解用法

    目录 一.前言 二.数组怎么样 三.替代方法 3.1 解析 List 3.2 解析 Set 3.3 解析 Map 四.后续 一.前言 在日常开发中,经常会遇到需要在配置文件中,存储 List 或是 Map 这种类型的数据. Spring 原生是支持这种数据类型的,以配置 List 类型为例,对于 .yml 文件配置如下: test: list: - aaa - bbb - ccc 对于 .properties 文件配置如下所示: test.list[0]=aaa test.list[1]=bbb

  • SpringBoot中定时任务@Scheduled注解的使用解读

    目录 概述 注解定义 参数说明 源码解析 使用详解 定时任务同步/异步执行 fixedRate/fixedDelay区别 项目开发中,经常会遇到定时任务的场景,Spring提供了@Scheduled注解,方便进行定时任务的开发 概述 要使用@Scheduled注解,首先需要在启动类添加@EnableScheduling,启用Spring的计划任务执行功能,这样可以在容器中的任何Spring管理的bean上检测@Scheduled注解,执行计划任务 注解定义 @Target({ElementTyp

  • SpringBoot中的@ApiModelProperty注解作用

    目录 @ApiModelProperty注解作用 主要字段说明 举个简单的例子 @ApiModelProperty()失效 解决方法 @ApiModelProperty注解作用 @ApiModelProperty()注解用于方法.字段,表示对model属性的说明或者数据操作更改,以下是它的源码: // IntelliJ API Decompiler stub source generated from a class file // Implementation of methods is no

随机推荐