Spring事务的几种坑,稍微不注意就会导致事务失效

对于从事Java开发的小伙伴来说,spring事务应该是非常熟悉的;在某些业务场景下,同时有多张表的写入操作,为了确保原子性,我们一般都会使用spring事务;spring事务在大多数情况下都可以满足需求,但同时他也有很多坑会导致事务失效。

我列举以下几点看看

1.错误的访问权限

@Service
public class TestService {

    @Autowired
    private Mapper mapper;
    
    @Transactional
    private void test(Model model) {
        mapper.insert(model);
    }
}

 因为 add() 方法的访问修饰符被定义成了 private,所以导致了事务失效,spring 要求被代理的方法必须是由 public 修饰的。

因为AbstractFallbackTransactionAttributeSource类的computeTransactionAttribute方法中有个判断,如果目标方法不是public,则TransactionAttribute返回null,即不支持事务。

2.方法被定义成 final

@Service
public class TestService {

    @Autowired
    private Mapper mapper;

    @Transactional
    public final void add(Model model) {
        mapper.insert(model);
    }
}

由于 add 方法被定义成 final ,这样导致了 spring 的 aop 动态代理生成的代理对象不能复写该方法,导致事务失效。

3.方法的内部调用

@Service
public class TestService {

    @Autowired
    private Mapper mapper;

    @Transactional
    public void test(Model model) {
        mapper.insert(model);
        update(model);
    }

    @Transactional
    public void update(Model model) {
        // doSomeThing();
    }
}

我们看到在事务方法add中,直接调用事务方法updateStatus。从前面介绍的内容可以知道,updateStatus方法拥有事务的能力是因为spring aop生成代理了对象,但是这种方法直接调用了this对象的方法,所以updateStatus方法不会生成事务。

4.当前实体对象没有被spring管理

这种情况就不上代码了,简单来说就是没有加注解,像 service 层没有加上 @Service 注解等,没有交给 spring 管理 Bean 实例,所以也不会生成事务。

5.抛出了异常但是被自己捕获了

@Transactional
    public void test(Model model) {
        try {
            mapper.insert(model);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

如图所示,方法抛出了异常被自己捕获了,又没有重新抛出。事务的 AOP 无法捕获异常,导致出现了异常事务无法回滚。

6.数据库默认存储引擎不支持事务

msql8以前的版本数据库引擎是支持myslam和innerdb的。我以前也用过,对应查多写少的单表操作,可能会把表的数据库引擎定义成myslam,这样可以提升查询效率。但是,要千万记得一件事情,myslam只支持表锁,并且不支持事务。所以,对这类表的写入操作事务会失效。

这是写的第一篇博客,就先简单介绍一下 spring 事务常见的几种失效常见,往后我会不断更新我在工作中碰到的一些 bug、技巧等;感谢小伙伴的支持!

猜你喜欢

转载自blog.csdn.net/m0_64055755/article/details/127514239