Spring事务(二)-@Transactional事务失效的场景


  有时候,我们明明在类或者方法上添加了@Transactional注解,却发现方法并没有按事务处理。其实,以下场景会导致Spring的@Transactional事务失效。

1、事务方法所在的类没有加载到Spring IOC容器中。

  @Transactional是Spring的注解,未被Spring管理的类中的方法不受@Transactional注解控制,这个应该很好理解。

2、方法没有被public修饰。

  众所周知,java的访问权限修饰符有:privatedefaultprotectedpublic四种,但是@Transactional注解只能作用于public修饰的方法上。具体为什么会这样,我也没理解,就先记住吧。

3、在同一个类中的方法调用@Transactional方法。

  假如在同一个类中有A、B两个方法,如下:

@Service
public class UserServiceImpl {

    @Autowired
    UserMapper userMapper;

    public void A() {
        B();
    }

    @Transactional
    public void B() {
        userMapper.deleteById(1);
        int i = 10 / 0; //模拟发生异常
    }
    
}

像上面的代码,B方法使用@Transactional注解标注,在A()方法中调用了B()方法,在外部调用A()方法时,B()方法的事务不会生效。这是由于使用Spring AOP代理造成的,因为只有当事务方法被当前类以外的代码调用时,才会由Spring生成的代理对象来管理。

4、方法的事务传播类型不支持事务。

  当@Transactional的propagation设置为NOT_SUPPORTED时,也就是@Transactional方法总是非事务方式执行。(Spring事务传播行为可以查阅我之前的一篇文章:Spring事务(一)-事务传播行为

5、不正确地捕获异常。

  使用了try-catch代码块将异常捕捉了,没有向上抛出异常,事务不会回滚。

6、标注错误的异常类型。

  Spring事务默认回滚类型是RuntimeException类型,如果没有制定回滚的类型,抛出的错误不是RuntimeException类型,则无法回滚。

7、数据库不支持事务。

  以MySQL为例,InnoDB引擎是支持事务的,而像MyISAM、MEMORY等是不支持事务的。 从MySQL5.5.5开始默认的存储引擎是InnoDB,之前默认都是MyISAM。

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/289741.html

(0)
上一篇 2022年9月16日
下一篇 2022年9月16日

相关推荐

发表回复

登录后才能评论