栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

SpringBoot事务失效场景

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

SpringBoot事务失效场景

一.事务不生效

1.访问权限的问题

如果我们在开发过程中,把有事务的方法定义了错误的权限,就会导致事务功能出错。众所周知,spring要求被代理的方法必须是public的。说白了,在AbstrctFallbackTransactionAttributedSource类的computeTransactionAttribute方法中有个判断,如果目标不是public则TransactionAttribute返回的是空

protected TransactionAttribute computeTransactionAttribute(Method method, Class targetClass) {
        if (this.allowPublicMethodsonly() && !Modifier.isPublic(method.getModifiers())) {
            return null;
        } else {
            Class userClass = ClassUtils.getUserClass(targetClass);
            Method specificMethod = ClassUtils.getMostSpecificMethod(method, userClass);
            specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
            TransactionAttribute txAttr = this.findTransactionAttribute(specificMethod);
            if (txAttr != null) {
                return txAttr;
            } else {
                txAttr = this.findTransactionAttribute(specificMethod.getDeclaringClass());
                if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
                    return txAttr;
                } else {
                    if (specificMethod != method) {
                        txAttr = this.findTransactionAttribute(method);
                        if (txAttr != null) {
                            return txAttr;
                        }

                        txAttr = this.findTransactionAttribute(method.getDeclaringClass());
                        if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
                            return txAttr;
                        }
                    }

                    return null;
                }
            }
        }
    }

2.方法被final修饰

spring事务底层使用的是aop,也就是哦通过jdk动态代理或者cglib动态代理,如果某个方法使用final修饰后,在代理类中就无法重写。

3,方法内部调用

比如在service某个事务方法中调用了另外一个事务方法。事务会失效

    @Transactional
     public  void doSomeThing() {
        Random random = new Random();
        Integer s = random.nextInt(100);
        Mamber mamber = new Mamber(s, "zhangsan", "123");
        mamberMapper.saveData(mamber);
        int i =1/0;
        updateData(mamber);
    }
    @Transactional
    public void updateData(Mamber mamber){
        mamber.setName("lisi");
        mamberMapper.updateData(mamber);
    }

   是因为在调用updateData的时候,用了this对象的方法,又因为是动态代理,所以updateData不会生成事务

如何解决 就是在Service中用@Autowired把自己注入进来,因为有三层缓存的存在,所以不会产生循环依赖,用service调用updateData方法

4.没有写@Service  就是没有被Spring管理

5.多线程调用

因为不同的线程调用的是不同的数据库链接,这个数据库连接是用ThreadLocal保存的, 多个线程会有多个ThreadLocal,所以链接不同了,事务也就失效了

6.表不支持事务  比如MyISAM

7.未使用@Transactional注解

二.事务不回滚

1.错误的传播特性

spring支持7种传播特性

REQUIRED 如果当前上下文存在事务,那么加入该事务,不存在事务就创建一个事务(默认)

SUPPORTS 如果当前上下文存在事务,则支持事务加入事务,如果不存在事务,就使用非事务的方式执行

MANDATORY 如果当前上下文存在事务,否认抛出异常

NOT_SUPPORTS 如果当前上下文存在事务,则挂起当前事务,然后新的方法在没有事务的环境下执行

NEVER 如果上下文存在事务则抛出异常,否则在无事务环境上执行代码

NESTED 如果上下文存在事务,则嵌套事务执行,如果不存在事务,则新建事务

2.自己吞了异常

事务不回滚 可能是开发者在代码中手动try catch了异常

3.手动抛出别的异常

即使开发者没有手动捕获异常,但是如果抛出的异常不正确,spring事务也不会回滚

默认情况下只会回滚RuntimeException 和Error。对于普通异常不会回滚

4.自定义异常

在使用@Transactional注解生命十五是,有时候我们想自定义回滚的异常,spring也是支持的,可以通过设置rollbackFor参数来完成这个功能

rollBack默认值是UncheckdException包括RuntimeException和Error

所以建议设置成Exception或者Throwable.

5.嵌套事务回滚多了

还是上面事务方法调用了另一个事务方法,但是我不想让第一个事务方法中回滚,那么只需要在另一个事务方法中手动捕获异常就可以了

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/695229.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号