美文网首页
SpringBoot 事务管理

SpringBoot 事务管理

作者: IT前沿技术分享 | 来源:发表于2020-09-05 17:51 被阅读0次

一、springboot的事务事务管理

我们在开发企业应用时,对于业务人员的一个操作实际是对数据读写的多步操作的结合。由于数据操作在顺序执行的过程中,任何一步操作都有可能发生异常,异常会导致后续操作无法完成,此时由于业务逻辑并未正确的完成,之前成功操作数据的并不可靠,需要在这种情况下进行回退。

事务的作用就是为了保证用户的每一个操作都是可靠的,事务中的每一步操作都必须成功执行,只要有发生异常就回退到事务开始未进行操作的状态。

事务管理是Spring框架中最为常用的功能之一,我们在使用Spring Boot开发应用时,大部分情况下也都需要使用事务。

二、springboot事务管理方式

spring支持编程式事务管理声明式事务管理两种方式。

编程式事务管理

编程式事务管理使用TransactionTemplate或者直接使用底层的PlatformTransactionManager。对于编程式事务管理,spring推荐使用TransactionTemplate。

声明式事务管理

声明式事务管理建立在AOP之上的。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。

声明式事务管理也有两种常用的方式,一种是基于tx和aop名字空间的xml配置文件,另一种就是基于@Transactional注解。显然基于注解的方式更简单易用,更清爽。

**@Transactional **注解的方式,是目前流行的使用方式,下面简单介绍一下,如何使用@Transactional注解方式的事务

三、使用@Transactional 注解进行事务管理

1.启用事务管理功能

在关键类中添加 注解 @EnableTransactionManagement,开启事务支持

如,app入口类

@SpringBootApplication(scanBasePackages = {"com.a.b.c", "cn.afterturn.easypoi"})
@EnableCaching
@EnableFeignClients
@EnableScheduling
@EnableTransactionManagement
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
public class MyApplication {    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

或者 mybatis配置类中

@EnableTransactionManagement
@Configuration
@MapperScan(basePackages = {"com.a.b.c.*"})
public class MybatisPlusConfig {}

2.添加@Transactional到对应的方法中

public class AccountServiceImpl implements AccountService{
       @Autowired
     private AccountDao accountDao;
      @Transactional
     public void transfer(int outter, int inner, Integer money) {
          accountDao.moveOut(outter, money); //转出
         int i = 1/0;  // 抛出异常
         accountDao.moveIn(inner, money); //转入
 
     }
 }

在方法transfer上添加了@Transactional的注解,运行后,抛出异常,事务生效。

3.@Transactional对异常的拦截

上文的事务写法,一切都非常顺利,但是,如果transfer方法体内抛出异常的方式,修改为Exception,如下

public class AccountServiceImpl implements AccountService{
       @Autowired
     private AccountDao accountDao;
      @Transactional
     public void transfer(int outter, int inner, Integer money) {
          accountDao.moveOut(outter, money); //转出
         throw new Exception("失败!");  // 抛出异常
         accountDao.moveIn(inner, money); //转入
 
     }
 }

那么,事务就不奏效了,为什么呢?

因为,@Transactional 注解的方式,是基于Spring AOP的事务管理 ,即声明式事务管理,默认是针对RuntimeException回滚,即默认只对RuntimeException()及其子类进行事务回滚;非运行时类型的异常默认是不会回滚的。

Image_20200906185422.png

spring aop 异常捕获原理:被拦截的方法需显式抛出异常,并不能经任何处理,这样aop代理才能捕获到方法的异常,才能进行回滚,默认情况下aop只捕获 RuntimeException 的异常,但可以通过配置来捕获特定的异常并回滚

换句话说在service的方法中不使用try catch 或者在catch中最后加上throw new runtimeexcetpion(),这样程序异常时才能被aop捕获进而回滚

所以, 默认情况下,非运行时类型的异常默认是不会回滚的。

故,要实现任何异常情况的回滚,则需要修改@Transactional的属性rollbackFor的值为Exception.class

public class AccountServiceImpl implements AccountService{
       @Autowired
     private AccountDao accountDao;
      @Transactional(rollbackFor=Exception.class)
     public void transfer(int outter, int inner, Integer money) {
          accountDao.moveOut(outter, money); //转出
         throw new Exception("失败!");  // 抛出异常
         accountDao.moveIn(inner, money); //转入
 
     }
 }

四、@Transactional 注解的属性

SpringBoot 事务管理

相关文章

网友评论

      本文标题:SpringBoot 事务管理

      本文链接:https://www.haomeiwen.com/subject/fbyfektx.html