首页 > 其他分享 >springboot 事务

springboot 事务

时间:2022-12-21 21:45:59浏览次数:54  
标签:回滚 springboot 方法 Transactional 事务 异常 public

springboot 事务

笔记详情 (bilibili.com)

1. 快速使用

  • 事务支持
备注:使用事务的时候,一定要首先确保当前数据库的引擎是否支持事务,如果数据库引擎不支持事务,则任何配置都是徒劳的。
​
例如:MySQL 数据库 InnoDB 支持事务,而 MyISAM 不支持事务。
  • 引入依赖
备注:已经引入了 mybatis-plus-boot-starter 则无需再次引入 spring-boot-starter-jdbc。
原因:mybatis-plus-boot-starter 内部已经引入了 spring-boot-starter-jdbc。
<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>mybatis-plus-boot-starter</artifactId>
  <version>${mybatis.version}</version>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-jdbc</artifactId>
  <version>${jdbc.version}</version>
</dependency>
  • 添加注解
备注:注解一般添加在自己的业务方法上面 (一般来说都是添加在 service 层的方法上面)
package com.dme.modules.service.transactional.impl;
/**
 * @Author: 喜欢编程的代先生
 * @Date: 2022-06-12 12:39
 * @Description: 拒绝侵权
 */
@Service
public class TransactionServiceImpl extends ServiceImpl<TransactionDemoDao,TransactionOne> implements TransactionService {
​
  private Logger logger = LoggerFactory.getLogger(TransactionServiceImpl.class);
​
  private TransactionDemoDao transactionDemoDao;
​
  @Autowired
  public void setTransactionDemoDao(TransactionDemoDao transactionDemoDao) {
    this.transactionDemoDao = transactionDemoDao;
 }
​
  @Transactional(rollbackFor = Exception.class)
  @Override
  public void testDelete() {
    logger.info("测试删除........");
    int i = transactionDemoDao.deleteById("1539393513600253961");
    logger.info("受影响行数 :" + i);
    int a = 1 / 0;
 }
}

 

 

2. 详细介绍

在 Spring 中,事务的实现方式有两种,分别是编程式事务和声明式事务管理两种方式。
  • 编程式事务管理
编程式事务管理使用 TransactionTemplate或者直接使用底层的 PlatformTransactionManager。对于编程式事务管理,spring 推荐使用 TransactionTemplate。
  • 声明式事务管理
声明式事务管理建立在 AOP 之上,其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行目标方法之后根据执行的情况提交或者回滚事务。声明式事务管理不需要入侵代码,通过 @Transactional 就可以进行事务的操作,推荐使用。

1. 事务注解

备注:@Transactional 只能放在 public 修饰的方法上。默认情况下,该注解只对 RuntimeException 及其子类异常执行事务回滚。

参数名称功能描述readOnly该属性用于设置当前事务是否为只读模式,设置为 true 表示只读,false 表示可读可写,默认情况下是 false。

例如: @Transactional(readOnly = true)rollbackFor该属性用于设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚。

例如:

指定单一异常类:@Transactional(rollbackFor = Exception.class)

指定多个异常类:@Transactional(rollbackFor = {RuntimeException.class,Exception.class})rollbackForClassName该属性用于设置需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,则进行事务回滚。

例如:

指定单一异常类名:@Transactional(rollbackForClassName = "RuntimeException")

指定多个异常类名:@Transactional(rollbackForClassName = {"RuntimeException","Exception"})noRollbackFor该属性用于设置不需要进行回滚的异常类数组。使用方法同 rollbackFornoRollbackForClassName该属性用于设置不需要进行回滚的异常类名称数组。使用方法同 rollbackForClassNamepropagation该属性用于设置事务的传播行为。isolation该属性用于设置事务的隔离级别。timeout该属性用于设置事务的超时秒数,默认值为 -1 表示永不超时。

2. 隔离级别

  • 隔离级别
数据库标准提出了四种事务隔离级别,分别为:读未提交、读已提交、可重复读、串行化。
  • 枚举映射
package org.springframework.transaction.annotation;
​
public enum Isolation {
  DEFAULT(-1), // springboot 默认隔离级别,可以通过配置文件进行配置
  READ_UNCOMMITTED(1), // 读未提交
  READ_COMMITTED(2), // 读已提交
  REPEATABLE_READ(4), // 可重复读
  SERIALIZABLE(8); // 串行化
​
  private final int value;
​
  private Isolation(int value) {
    this.value = value;
 }
​
  public int value() {
    return this.value;
 }
}
​
  • 使用方法
@Transactional(isolation = Isolation.DEFAULT)
public void testAdd(){
  logger.info("测试默认隔离级别......");
}

3. 传播行为

  • 7 种传播行为
springboot 事务机制种对数据库存在七种传播行为,常用的传播行为主要有三种:REQUIRED、REQUIRES_NEW、NESTED
REQUIRED:需要事务,它是默认的传播行为,如果当前存在事务,就沿用当前事务,否则新建一个事务运行子方法。
SUPPORTS:支持事务,如果当前存在事务,就沿用当前事务,如果不存在事务,则继续采用无事务的方式运行子方法
MANDATORY:必须使用事务,如果当前没有事务,则会抛出异常,如果当前存在事务,就沿用当前的事务。
REQUIRES_NEW:无论当前事务是否存在,都会创建新的事务去运行子方法,这样新事务就可以拥有新的锁和隔离级别等特性,与当前事务相互独立。
NOT_SUPPORTED:不支持事务,如果当前存在事务,则将事务挂起,运行子方法。
NEVER:不支持事务,如果当前方法存在事务,则抛出异常,否则继续使用无事务机制继续运行。
NESTED:当前方法调用子方法时,如果子方法发生异常,则回滚子方法执行过的 SQL,而不回滚当前方法的事务。
  • 枚举映射
package org.springframework.transaction.annotation;
​
public enum Propagation {
  REQUIRED(0),
  SUPPORTS(1),
  MANDATORY(2),
  REQUIRES_NEW(3),
  NOT_SUPPORTED(4),
  NEVER(5),
  NESTED(6);
​
  private final int value;
​
  private Propagation(int value) {
    this.value = value;
 }
​
  public int value() {
    return this.value;
 }
}
  • 使用方法
@Transactional(propagation = Propagation.NESTED)
public void testPropagation(){
  logger.info("测试事务传播行为......");
}

4. 事务超时

事务超时,就是指一个事务所允许执行的最长时间,如果超过该时间限制事务还未完成,则自动回滚事务。在 TransactionDefinition 中以 int 的值来表示超时时间,其单位是秒。默认设置为底层数据库事务系统的超时值,如果底层数据库事务系统没有设置超时值,那么就是 none,即没有超时限制。

5. 回滚机制

  • 自动回滚
备注:对可能出现异常的地方不要进行 try catch 操作。
@Transactional(rollbackFor = Exception.class)
public void testRollback(){
  logger.info("测试异常自动回滚......");
}
  • 手动回滚
备注:对可能出现异常的地方进行 try catch,并在 捕获异常的同时进行回滚的操作。
@Transactional(rollbackFor = Exception.class)
public void testRollback(){
  logger.info("测试异常自动回滚......");
  try {
    int i = 1 / 0;
 }catch (Exception e){
    logger.error("异常信息:" + e.getMessage());
    TransactionStatus transactionStatus = TransactionAspectSupport.currentTransactionStatus();
    transactionStatus.setRollbackOnly();
 }
}
  • 设置回滚点
备注:将当前操作回滚到设置的回滚点的位置。
@Transactional(rollbackFor = Exception.class)
public void testRollback(){
  logger.info("业务逻辑一...........");
  logger.info("业务逻辑二...........");
  /**设置回滚点*/
  Object savepoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
  logger.info("业务逻辑三...........");
  logger.info("测试异常自动回滚......");
  try {
    int i = 1 / 0;
 }catch (Exception e){
    logger.error("异常信息:" + e.getMessage());
    TransactionStatus transactionStatus = TransactionAspectSupport.currentTransactionStatus();
    /**回滚到指定位置,也就是说,业务逻辑一和业务逻辑二的逻辑不会进行回滚*/
    transactionStatus.rollbackToSavepoint(savepoint);
 }
}

 

 

3. 常见问题

1. @EnableTransactionManagement

问题:springboot 项目中是否需要在 启动类上添加 @EnableTransactionManagement 注解?
答案:不需要。因为 springboot 自动装配已经帮助我们处理了,springboot 项目默认支持了事务。

2. @Transactional 失效

问题:方法上添加了 @Transactional 注解,为什么没有进行回滚?
排查一:是否使用了 try catch 进行了异常捕获,并且捕获之后,没有通过 throw new RuntimeException(); 进行异常抛出。因为对于 spring aop 异常捕获原理,被拦截的方法需要显示的抛出异常,并不能进行任何处理,这样 aop 代理才能捕获到方法的异常,才能进行事务的回滚操作;默认清空下,aop 只捕获 RuntimeException 的异常,但是可以通过配置来捕获特定的异常并回滚。
排查二:是否使用了 try catch 进行了异常信息捕获,如果是可以在 catch 语句中添加:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 
排查三:排查是不是产生了自调用的问题。在 spring 的 aop 代理下,只有目标方法被外部调用,目标方法才由 spring 生成的代理对象来管理;若统一类中的其他没有用 @Transactional 注解进行修饰的方法内部调用了 用 @Transactional 注解进行修饰的方法,有 @Transactional 注解的方法的事务将会被忽略,不发生回滚。
​
备注:如果确实需要这样操作,只需要把 @Transactional 注解加在当前的类名上就可以了 或者使用 AspectJ 取代 spring aop 进行代理。
排查四:@Transactional 注解只被应用到 public 修饰的方法上;如果在 protected、private等修饰的方法上,@Transactional 注解不会报错,但是这个注解的将不会生效。
排查五:@Transactional 注解不会对当前修饰的方法的子方法生效。比如:我们在方法 A 中声明了 @Transactional 注解,但是 A 方法的内部调用的 方法 B 和 方法 C,其中方法 B 进行了 数据库的操作,但是改部分的异常被方法 B 进行了处理并且没有进行 抛出,这样的话事务是不会生效的。反之,如果 方法 B 声明了 @Transactional,但是方法 A 没有声明 @Transactional,A 方法内部调用 B 方法,事务也是不会生效的。如果想要事务生效,需要将子方法的事务控制交给调用的方法,在子方法中使用 @Transactional注解并通过 rollbackFor 指定定回滚的异常 或者直接将 异常 抛出。
​
备注:在使用事务的时候,最好把子方法的异常进行抛出,交给调用的方法进行处理。

 

标签:回滚,springboot,方法,Transactional,事务,异常,public
From: https://www.cnblogs.com/jiangzishun/p/16997287.html

相关文章

  • SpringBoot大文件上传详解及实例代码
    ​ 前言文件上传是一个老生常谈的话题了,在文件相对比较小的情况下,可以直接把文件转化为字节流上传到服务器,但在文件比较大的情况下,用普通的方式进行上传,这可不是一个好......
  • SpringBoot的学习
    SpringBootSpringBoot最核心的东西:自动装配!!!很重要!以及他的SpringApplication.run(); 方法配置用什么写:可以用xml,和springboot自带的yaml自动装配原理?重要:涉及......
  • Spring提取@Transactional事务注解的源码解析
    Spring提取@Transactional事务注解的源码解析声明:本文是自己在学习​​spring​​注解事务处理源代码时所留下的笔记;难免有错误,敬请读者谅解!!!1、事务注解标签<tx:annotatio......
  • java 实现文件夹上传(springBoot 框架)
    有时我们后台管理等服务可能会有这样一个简单需求,就是根据文件夹将整个文件夹下的所有资源都上传到我们的服务器上,本人也是搜索了大量资料,最终以最简单便捷的方式实现该功......
  • 【源码透视】SpringBoot的SPI机制
    一、从java类加载机制说起java中的类加载器负载加载来自文件系统、网络或者其他来源的类文件。jvm的类加载器默认使用的是双亲委派模式。三种默认的类加载器BootstrapCla......
  • KingbaseES V8R6 空闲事务会话超时自动终止机制
    背景如果会话在事务中停留的时间过长,则允许自动终止空闲会话。可以由配置参数idle_in_transaction_session_timeout事务处于空闲状态的时长,它有助于防止被遗忘的交易事务......
  • 【源码透视】SpringBoot的SPI机制
    一、从java类加载机制说起java中的类加载器负载加载来自文件系统、网络或者其他来源的类文件。jvm的类加载器默认使用的是双亲委派模式。三种默认的类加载器BootstrapCl......
  • 基于Springboot+Mybatis+mysql+element-vue高校就业管理系统
    @目录一、系统介绍二、功能展示1.用户登陆注册2.个人信息(学生端)3.查看企业岗位信息(学生端)4.我的应聘(学生端)5.学生信息管理(辅导员)6.三方协议书审核(辅导员)7.查看班级就业......
  • 基于Springboot+Element-Vue-Admin实现简单权限管理系统
    @目录一、系统介绍二、功能展示1.用户登陆2.用户管理3.权限管理、权限设置4.菜单管理三、数据库展示四、其它1.数据库表2.获取源码一、系统介绍系统主要功能:系统实现了用......
  • 基于Java springboot+mybatis+mysql实现的校园新闻系统
    @目录一、系统介绍二、功能展示1.主页2.登录以及注册3.普通用户对新闻咨询的编辑、发布和删除4.管理员对新闻的审核发布和撤销取消发布三、代码展示四、获取源码一、系统......