spring事务失效的11种场景

原文地址:spring事务失效的11种场景 – 编程屋

1 访问权限问题:

java的访问权限有4种:private、default、protected、public,它们的权限从左到右,以此变大。如果在开发中,将事务方法定义了错误的访问权限,则事务功能会失效。

@Service
public class EmpService {

    @Transactional
    private void add(UserModel userModel){
        saveData(userModel);
    }
}

如上:add方法的权限被定义成了private,这样会导致事务失效,spring要求被代理方法必须是public的。、

在Spring源码中,如果目标方法不是public,则TransactionAttribute返回null,不支持事务。

2 方法用final修饰

@Service
public class EmpService {

    @Transactional
    public final void add(UserModel userModel){
        saveData(userModel);
    }
}

放方法被final修饰时,也会导致事务失效。

因为spring事务底层是用了aop,用了jdk的动态代理或者cglb的动态代理,会帮我们生成代理类,在代理类中实现事务功能。

如果某个方法被final修饰了,那么在代理类中,就无法重新该方法,而添加事务功能。

注意:如果某个方法被static修饰,同样也无法通过动态代理,变成事务方法。

3 直接调用内部方法

@Service
public class EmpService {

    @Transactional
    public void add(UserModel userModel){
        saveData(userModel);
        updateSataus(userModel);
    }


    @Transactional
    public void updateSataus(UserModel userModel){
        doSomething();
    }
}

由上可知:在事务方法add可知,它直接调用了updateStatus方法,由2可知:方法拥有事务的能力是因为spring aop中生成了代理对象,但是直接调用updateStatus方法不会直接生成事务。但是可以直接将该类直接注入进来,比如:

@Service
public class EmpService {

    private EmpService empService;

    @Transactional
    public void add(UserModel userModel){
        saveData(userModel);
        empService.updateSataus(userModel);
    }


    @Transactional(rollbackFor = Exception.class)
    public void updateSataus(UserModel userModel){
        doSomething();
    }
}

这样事务就生效了,也不会穿生循环依赖的问题。

4 未被Spring管理

public class EmpService {


    @Transactional
    public void add(UserModel userModel){
        saveData(userModel);
        updateSataus(userModel);
    }
    
}

如图:没有将该类交给spring管理

5 多线程调用

        由以下代码可知:在add()事务方法里面,调用了updateStatus事务方法,但是updateStatus事务方法是在另外一个线程中调用的。这样就导致了两个方法不在同一个线程中,获取到了数据库连接不一样,从而是两个不同的事务,如果updateStatus方法中抛出了异常,add方法是不会回滚的

@Service
public class EmpService {

    @Autowired
    private OrderService orderService;


    @Transactional
    public void add(UserModel userModel){

        new Thread(()->{
            orderService.updateSataus();
        }).start();
    }

}

@Service
public class OrderService{

    @Transactional
    public void updateSataus(){
        System.out.println("======================");
    }

}

        spring的事务是通过数据库的连接来实现的。当前线程中保存了一个map,key是数据源,value是数据库连接。同一个事务,指同一个数据库连接,只有拥有同一个事务连接才能保证同时提交和回滚。如果是不同的线程,拿到的数据库连接肯定是不同的。

6 表不支持事务

如果表的引擎是myisam,那么它是不支持事务的,要想支持事务,改成innodb引擎

7 事务没有开启

如果是springBoot项目,那么是事务默认是开启的,但如果是spring项目,需要xml配置

以上只是部分内容,为了维护方便,本文已迁移到新地址:spring事务失效的11种场景 – 编程屋

  • 14
    点赞
  • 89
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值