@Transaction的自调用失效问题

946 阅读1分钟

有时候配置了@Transaction注解,但是它会失效,这里我们要注意一些细节的问题,以避免掉入陷阱。 注解@Transaction的底层原理是Spring Aop技术,而Spring Aop技术使用的是动态代理,这就意味着对于静态方法非public方法,注解@Transaction会失效,当然我们在实际开发中有一个更为神秘的错误,就是发生自调用。 所谓自调用方法,就是一个类的方法去调用自身另外一个方法的过程。

 @Service
 public class RoleServiceImpl implements RoleService{
 	@Autowired
    private RoleMapper roleMapper = null;
    @Override
    @Transaction(propagation = Propagation.REQUIRES_NEW, isolation= Isolation.READ_COMMITTIED)
    
    public int insertRole(Role role){
    	return roleMapper.insertRole(role);
    }
 	
    @Override
    @Transaction(propagation = Propagation.REQUIRED isolation= Isolation.READ_COMMITTIED)
    
    public int insertRoleList(List<Role> roleList){
    	int count = 0;
        for(Role role : roleList){
        try{
        	// 调用自身类的方法,产生了自调用的问题
            insertRole(role);
            count ++;
        }catch(Exception e){
        	e.printStackTrace();
        	}
        }
    	return count;
    }
 
 }

上述代码的问题中,insertRole方法的实现中,它调用了自身类的实现insertRole方法,但是呢,insertRole申明了Propagation.REQUIRES_NEW的传播行为,也就是每一次调用就要产生新的事务运行,相当于这些方法自己调用自己的方法,换句话说,压根不存在代理对象的调用。那么就不会出现@Transaction的方法,出现了自调用注解失效的问题。

   // 解决办法就是 直接从Spring Ioc容器中获取R哦了Service的代理对象
    @Override
    @Transaction(propagation = Propagation.REQUIRED, isolation= Isolation.READ_COMMITTIED)
    
    public int insertRoleList(List<Role> roleList){
    	int count = 0;
        // 从容器中获取RoleService对象,实际上就是代理对象
        
        ApplicationContext context = new ClassPathXMlApplicationContext(“application-cfg.xml”);
        RoleService service = context.getBean(RoleService.class);
        
        for(Role role : roleList){
        try{
            service.insertRole(role);
            count ++;
        }catch(Exception e){
        	e.printStackTrace();
        	}
        }
    	return count;
    }
    }