1.springboot事务-使用的前提

135 阅读3分钟

springboot中使用事务的前提

1.前提一,需要加入的依赖

其实事务最基础的包只要在pom文件加入spring-tx依赖即可,但是一般情况下我们会使用mybatis作为操作数据库的中间件。当我们依赖mybatis时,连带这就把事务需要的包依赖进来了。

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>${mybatis-spring-boot-starter.version}</version>
</dependency>

依赖关系如下:

image-20220817094309763

2.前提二,启动类上加批注

@EnableTransactionManagement

在springboot中是不需要加入此注解的。默认就开启了事务。但是加上也无所谓,还能表明本程序中用到了事务。

所以这步加不加就看个人意愿了。

3.前提三,数据库需要支持事务

这里拿mysql5.7为例,其默认的引擎就是InnoDB。它有两种引擎:

  • MyISAM:没有commit 和rollback。所以不支持事务。但是具有高性能读取速度,适用于没有事务的场景。
  • InnoDB:支持事务,支持行锁等优点。缺点是没有保存表的行数,当使用COUNT统计时会扫描全表。适用于可靠性要求比较高,或者要求事务

创建表时指定引擎:

CREATE TABLE `user` (
`id`int(64) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8

4.前提四,事务方法上加批注

@Transactional(rollbackFor = Exception.class)

这里解释下为什么rollbackFor一定要指定Exception。Spring框架的事务管理默认地只在发生不受控异常(RuntimeException和Error)时才进行事务回滚。也就是说,当事务方法抛出受控异常(Exception中除了RuntimeException及其子类以外的)时不会进行事务回滚**。**

红色中写的很重要,这里再解释下什么叫受控异常和不受控异常。

  • 受控异常(checked exceptions):就是非运行时异常,即Exception中除了RuntimeException及其子类以外的。
  • 不受控异常(unchecked exceptions):RuntimeException和Error。
image-20220817094704747

有了上面的认知,再来看一下以前项目中我们定义的CommonException:

public class CommonException extends Exception {
    protected String code ;
    protected String message;
    
    public static CommonException buildCommonException(String code, String errorMsg) {
        return new CommonException(code, errorMsg);
    }

    public static CommonException buildCommonException(String errorMsg) {
        return new CommonException(Constants.COMMON_RESPONSE_CODE_ERROR, errorMsg);
    }
}

这里可以看到我们是直接继承了Exception类,而不是RuntimeException,还真是挺坑的!也就是说在我们抛出了CommonException时,如果方法上仅仅加了@Transactional而没有指定rollbackFor时,事务是不会回滚的!

5.前提五,事务方法的要求

  • 方法一定是要public类型的。private编译期直接报错;protected编译期不报错,但是无法回滚事务。
  • 在方法内不要使用try-catch捕获异常。不抛出异常,自然无法进行回滚。这里可以这样理解,就是springboot通过@Transactional批注对方法加了个AOP实现,springboot发现如果有你指定的异常类型发生时,对事务进行回滚。

使用前提总结

1. pom中加依赖:mybatis-spring-boot-starter
1. 启动类上加批注:@EnableTransactionManagement
1. mysql引擎:InnoDB
1. 事务方法上加批注:@Transactional(rollbackFor = Exception.class)
1. 事务方法必须是public
1. 方法内不要自己用try-catch进行捕获

OK , 注意到上面的这些方面,如果不是太不幸的话,基本应该是可以用了。但是后面还会再次总结下事务不能回滚的一些情况。