Spring中事务失效常见的场景-开发易踩坑

73 阅读2分钟

一、自定义异常处理被捕获

我们习惯性的将可能存在异常的函数使用try catch 进行捕获,如果该方法使用了声明式事务注解,那么事务将会失效。

@Transactional
public void tranErrTest() {
    // 业务代码

    try {
        // 模拟异常
        int a = 1 / 0;
    } catch (Exception e) {
        System.out.println(e);
        //throw new RuntimeException(e);
    }
}

代码分析:

1、业务代码部分省略,一般是需要处理事务问题的数据库更新或删除操作

2、@Transactional 注解标明该方法是一个事务体

3、由于代码模拟了异常产生,此时cacth将会被捕获并打印出异常

4、由于异常被捕获后没有再次抛出,此方法中的事务将会失效。

解决办法:

catch 块中再次将异常抛出即可,如代码注释部分开启事务后才会起作用。

二、抛出检查异常

@Transactional
public void tranErrTest2() throws FileNotFoundException {
    // 业务代码

    new FileInputStream("abcd");

    // 业务代码
}

代码分析:

1、new FileInputStream 将会抛出检查异常FileNotFoundException

2、一丹触发检查异常并没有再事务中声明,Spring将放弃事务处理

解决办法:

在@Transactional中增加回滚属性,如:@Transactional(roolbackFor=Exception.class)

三、非public方法导致事务失效

@Transactional
void tranErrTest3() {
    // 业务代码

}

代码分析:

1、注意方法上并没有public修饰,此时@Transactional将会失效

解决办法:

解决办法比较解答,加上public修饰即可。但这种情况在开发中比较容易忽略。

四、方法用final修饰

@Transactional
public final void tranErrTest4() {
    // 业务代码

}

代码分析:

1、示例代码中方法使用了final关键字修饰,此时@Transactional将会失效

解决办法:

解决就是如果需要使用Spring的事务管理,不要修饰为final,因为Spring事务底层是通过AOP实现的,如果方法是final或static修饰,那么AOP将无法通过动态代理变成事务方法。