SpringBoot~分析总结为何我的@Transactional 注解的方法没有被Spring Transaction Manager管理起来

出现的现象

  • 今天大致写了个下面的代码, 有点不符合我所理解的逻辑
@Controller
class ServiceImpl{
    @Autowired
    private UserService userService;

     public void doInsert(){
        this.insert(); //或者直接doInside();效果是一样的
    }
    
    @Transactional
    private void insert(){
        //do sql statement
    }
}

@Controller
class Test {
    @Autowired
    private ServiceImpl userService;
    
    public void test(){
        userService.insert();
    }
}
  • 当我执行了test中的test方法后,我的insert方法没有被Spring Transaction Manager管理起来。通过查找资料总结一下为何会出现下面的情况

总结@Transactional 注解不生效的几点原因

  1. 只对public修饰方法才起作用, 如果@Transactional 修饰的不是一个public方法, 就会失效, @Transactional 注解只被应用到 public 可见度的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错, 但是这个被注解的方法将不会展示已配置的事务设置。
  2. @Transactional 默认检测异常为RuntimeException及其子类以及程序错误, 如果有其他异常需要回滚事务的需要自己手动配置, 可以在@Transactional 注解里使用rollbackFor 属性明确指定异常。也可以使用noRollbackFor配置不会导致事务回滚的异常类数组
  3. 确保异常没有被try-catch{},catch以后也不会回滚, 在业务层手工捕捉并处理了异常(try…catch)等于把异常“吃”掉了,Spring自然不知道这里有错,更不会主动去回滚数据。
  4. 检查下自己的数据库是否支持事务,如mysql的mylsam就是不支持事务的
  5. 如果在同一个类中,一个非@Transactional 的方法调用有@Transactional 的方法不会生效,因为代理问题
  • @Transactional的实现原理是在业务方法外边通过Spring AOP包上一层事务管理器的代码(即插入切面, 切面上有事务的通知)

  • Spring AOP的底层有2种实现:JDK动态代理、CGLIB。前者的原理是JDK反射,并且只支持Java接口的代理;后者的原理是继承(extend)与覆写(override),因此能支持普通的Java类的代理。两种方式都是动态代理,即运行时实时生成代理。

  • 无论是何种代理, 代理类只是增强了被代理类,spring的事务管理机制是给代理类配置了, 并没有给被代理类配置事务管理器

  • 也就是说我们通过AOP切面是给代理类配置了事务管理机制, 并没有给被代理类配置事务管理机制, 我们知道通过代理类执行的方法最后还是要执行被代理类中的方法, 问题就出现在这,我们执行一个没有配置事务的代理类方法的时候,最后实在被代理类中执行了另一个方法, 而另一个方法在代理类中配置了事务管理机制, 但是我执行的是被代理类中的方法, 所以就不涉及到事务

  • 最后还有一点就是@Transactional 在方法上和类上的区别

  1. 在类上相当于在每个public方法上加上@Transaction
  2. 方法上的@Transactional 配置会覆盖类上的配置
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值