事务失效的场景?
权限问题,@Transactional 修饰的方法必须为public
方法用final修饰或者是static方法,spring事务底层使用了aop,也就是通过jdk动态代理或者cglib,帮我们生成了代理类,在代理类中实现的事务功能。但如果某个方法用final修饰了,那么在它的代理类中,就无法重写该方法,而无法添加事务功能。
方法内部调用 如果在某个Service类的某个方法中,调用另外一个事务方法,即在同一个类中的方法直接内部调用,事务会失效。m1中通过this的方式调用了m2方法,而this并不是代理对象,this.m2()不会被事务拦截器,所以事务是无效的
@Component public class UserService { public void m1(){ this.m2(); } @Transactional public void m2(){ //执行db操作 } }
如果外部直接调用通过UserService这个bean来调用m2方法,事务是有效的,上面代码可以做一下调整,如下,在UserService中注入了自己(或者在该Service类中使用AopContext.currentProxy()获取代理对象),此时m1中的m2事务是生效的
@Component public class UserService { @Autowired //这里注入了自己 private UserService userService; public void m1() { this.userService.m2(); } @Transactional public void m2() { //执行db操作 } }
未被spring容器管理 使用spring事务的前提是:对象要被spring管理,需要创建bean实例。通常情况下,我们通过@Controller、@Service、@Component、@Repository等注解,可以自动实现bean实例化和依赖注入的功能。如果类未被 Spring 管理,事务自然就失效了。
多线程调用 spring的事务是通过数据库连接来实现的。当前线程中保存了一个map,key是数据源,value是数据库连接。我们说的同一个事务,其实是指同一个数据库连接,只有拥有同一个数据库连接才能同时提交和回滚。如果在不同的线程,拿到的数据库连接肯定是不一样的,所以是不同的事务
异常情况 默认情况下,RuntimeException和Error的情况下,spring事务才会回滚。
通过try catch把异常捕获到处理了也不会回滚。