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