@Transactional注解控制事务有哪些不生效的场景

1. 数据库引擎不支持事务

      以mysql为例,其MyISAM引擎是不支持事务操作的,InnoDB才支持事务的引擎。从mysql5.5开始默认引擎是InnoDB,之前默认的是MyISAM,所以若底层引擎不支持事务注解也无能为力。。

2. 数据源没有配置事务管理器

3. 没有被spring管理

我们会把事务注解加到service层,如果没有@Service注解,这个类就不会被加载成一个Bean,那这个类就不会被spring管理,事务自然就失效了。。

4. 方法不是public的

根据spring官网,@Transactional只能用于public的方法上,否则事务不会生效,如果非要用在非public方法上,可以开启AspectJ代理模式。AspectJ使用加载时织入的方式,支持所有的pointcut,因此可以支持内部方法的事务设置。

5.@Transactional 注解属性 propagation 设置错误

  如注解配置的不支持事务,使用了Propagation。NOT_SUPPORTED:表示不易事务运行,当前若存在事务则挂起,详细可以参考博客:https://blog.csdn.net/duan196_118/article/details/103798804

6. 同一个类中方法调用,导致@Transactional失效

开发中避免不了会对同一个类里面的方法调用,比如有一个类Test,它的一个方法A,A再调用本类的方法B(不论方法B是用public还是private修饰),但方法A没有声明注解事务,而B方法有。则外部调用方法A之后,方法B的事务是不会起作用的。这也是经常犯错误的一个地方。

那为啥会出现这种情况?其实还是由于使用Spring AOP代理造成的,因为只有当事务方法被当前类以外的代码调用时,才会由Spring生成的代理对象来管理。

​
   //@Transactional
    @GetMapping("/test")
    private Integer A() throws Exception {
        CityInfoDict cityInfoDict = new CityInfoDict();
        cityInfoDict.setCityName("2");
        /**
         * B 插入字段为 3的数据
         */
        this.insertB();
        /**
         * A 插入字段为 2的数据
         */
        int insert = cityInfoDictMapper.insert(cityInfoDict);

        return insert;
    }

    @Transactional()
    public Integer insertB() throws Exception {
        CityInfoDict cityInfoDict = new CityInfoDict();
        cityInfoDict.setCityName("3");
        cityInfoDict.setParentCityId(3);

        return cityInfoDictMapper.insert(cityInfoDict);
    }

​

7. 异常被吃了

@Service
public class EmployeeServiceImpl implements EmployeeService{
    @Transactional
    public void updateEmployee(Employee employee){
        try{

        }catch{

        }
    }

}

把异常吃了,然后又不抛出来,事务怎么回滚呢?

8. 异常类型错误【@Transactional 注解属性 rollbackFor 设置错误】

上面的例子再抛出一个异常

​
@Service
public class EmployeeServiceImpl implements EmployeeService{
    @Transactional
    public void updateEmployee(Employee employee){
        try{

        }catch{
            throw new Exception(更新失败!!!"")
        }
    }

}

​

这样事务也是不生效的,因为默认回滚的是RuntimeException,如果你想要触发其它的异常回滚,需要在注解上配置:

@Transactional(rollbackFor = Exception.class)

这个配置仅限于Throwable异常类及其子类。

希望对看到的小伙伴有所帮助,欢迎各位留言。。。

你可能感兴趣的:(Spring)