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 在方法上和类上的区别