码农日记

薄洪涛的个人博客

spring中什么情况下事务会失效?

事务失效的场景?

  1. 权限问题,@Transactional 修饰的方法必须为public

  2. 方法用final修饰或者是static方法spring事务底层使用了aop,也就是通过jdk动态代理或者cglib,帮我们生成了代理类,在代理类中实现的事务功能。但如果某个方法用final修饰了,那么在它的代理类中,就无法重写该方法,而无法添加事务功能。

  3. 方法内部调用 如果在某个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操作
    }
}
  1. 未被spring容器管理 使用spring事务的前提是:对象要被spring管理,需要创建bean实例。通常情况下,我们通过@Controller、@Service、@Component、@Repository等注解,可以自动实现bean实例化和依赖注入的功能。如果类未被 Spring 管理,事务自然就失效了。

  2. 多线程调用 spring的事务是通过数据库连接来实现的。当前线程中保存了一个map,key是数据源,value是数据库连接。我们说的同一个事务,其实是指同一个数据库连接,只有拥有同一个数据库连接才能同时提交和回滚。如果在不同的线程,拿到的数据库连接肯定是不一样的,所以是不同的事务

  3. 异常情况 默认情况下,RuntimeException和Error的情况下,spring事务才会回滚。
    通过try catch把异常捕获到处理了也不会回滚。


  • 评论列表

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

Powered By Z-BlogPHP 1.7.3

版权所有 | 转载请标明出处