当前位置: 首页 > 图灵资讯 > 技术篇> Spring事务的几种坑,稍不注意就会导致事务失效

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

来源:图灵教育
时间:2023-06-06 09:30:15

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

1.访问权限错误

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

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

因为Abstractfalbacktransactionatributesoutesoutetractionatribute方法中有一个判断,如果目标方法不是public,transactionatribute返回null,即不支持事务。

2.该方法定义为finall

@Servicepublic class TestService {     @Autowired    private Mapper mapper;     @Transactional    public final void add(Model model) {        mapper.insert(model);    }}

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

3.内部调用方法

@Servicepublic 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、技巧等;感谢您的支持!