博客 分类专栏 专题 成员
Springboot 内部调用事务失效
2022-01-20 04:12:56
分类专栏: Java

事件

今天一个同事跑来帮我帮看个问题,她说她写的两个方法,一个事务生效,一个事务不生效,我也纳闷还有这种事,帮忙看了才发现问题。
两个方法大致是这么写的
生效的方式是这么写的

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveInfo(User user) {
		//do something
		this.saveUser(user);
		//do something	
	}

	public void saveUser(User user) {
		this.userMapper.insert(user);
	}

另外一个方法是这么写的(不生效)

	@Override
	public void saveInfo2(User user) {
		//do something
		this.saveUser2(user);
		//do something	
	}

	@Transactional(rollbackFor = Exception.class)
	public void saveUser2(User user) {
		this.userMapper.insert(user);
		//do something
	}

在 saveUser2中的方法事务不生效,因为她的需求是要 saveUser2有事务,saveInfo2不需要事务
咋一看两个方法,就是@Transactional 加的位置不一样而已
由于SpringBoot是通过代理来进行扩展功能的(@Transactional的意思是生成ServiceImpl的代理类时,会为saveInfo方法加上事务),这样的话,由于saveUser()没有声明事务,所以不会回滚。

错误的使用内部调用

	@Override
	public void saveInfo2(User user) {
		//do something
		this.saveUser2(user);
		//do something	
	}

	@Transactional(rollbackFor = Exception.class)
	public void saveUser2(User user) {
		this.userMapper.insert(user);
		//do something
	}

将注解加在内部方法中。

正确的方式

bean调用方法上添加注解

注解加在直接service调用的方法上,也就是最外层的方法上

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveInfo(User user) {
		//do something
		this.saveUser(user);
		//do something	
	}

	public void saveUser(User user) {
		this.userMapper.insert(user);
	}

注入内部bean

将service自己注入到service bean中


	@Resource
	@Lazy
	private ServiceImpl service

	@Override
	public void saveInfo2(User user) {
		//do something
		//使用内部service bean对象调用,不要用this
		service.saveUser2(user);
		//do something	
	}

	@Transactional(rollbackFor = Exception.class)
	public void saveUser2(User user) {
		this.userMapper.insert(user);
		//do something
	}

注意这里要加上@Lazy否则会出现
The dependencies of some of the beans in the application context form a cycle:
这个错误,就是循环依赖了,所以要延迟加在内部的bean,要使用 @Lazy 来注入内部bean
最后记得 启动类上加上 @EnableTransactionManagement