文章目录
事务不生效
方法内部调用
有时候我们需要在某个Service类的某个方法中,调用另外一个事务方法
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
@Transactional
public void add(UserModel userModel) {
userMapper.insertUser(userModel);
updateStatus(userModel);
}
@Transactional
public void updateStatus(UserModel userModel) {
doSameThing();
}
}
在事务方法add中,直接调用事务方法updateStatus。 updateStatus方法拥有事务的能力是因为spring aop生成代理了对象,但是这种方法直接调用了this对象的方法,所以updateStatus方法不会生成事务。
由此可见,在同一个类中的方法直接内部调用,会导致事务失效。
那么问题来了,如果有些场景,确实想在同一个类的某个方法中,调用它自己的另外一个方法,该怎么办呢?
修复方法一 : 【新加一个Service方法】
只需要新加一个Service方法,把@Transactional注解加到新Service方法上,把需要事务执行的代码移到新方法中。
具体代码如下:
@Servcie
public class ServiceA {
@Autowired
prvate ServiceB serviceB;
@Transactional
public void save(User user) {
queryData1();
queryData2();
serviceB.doSave(user);
}
}
@Servcie
public class ServiceB {
@Transactional(rollbackFor=Exception.class)
public void doSave(User user) {
addData1();
updateData2();
}
}
修复方法二:【在该Service类中注入自己】
如果不想再新加一个Service类,在该Service类中注入自己也是一种选择。
具体代码如下:
@Servcie
public class ServiceA {
@Autowired
prvate ServiceA serviceA;
@Transactional
public void save(User user) {
queryData1();
queryData2();
serviceA.doSave(user);
}
@Transactional(rollbackFor=Exception.class)
public void doSave(User user) {
addData1();
updateData2();
}
}
注入自己 spring ioc内部的三级缓存保证了它,不会出现循环依赖问题。
修复方法三:【通过AopContent类】<---- 推荐
在该Service类中使用AopContext.currentProxy()获取代理对象
上面的方法2确实可以解决问题,但是代码看起来并不直观,还可以通过在该Service类中使用AOPProxy获取代理对象,实现相同的功能。具体代码如下:
@Servcie
public class ServiceA {
@Transactional
public void save(User user) {
queryData1();
queryData2();
((ServiceA)AopContext.currentProxy()).doSave(user);
}
@Transactional(rollbackFor=Exception.class)
public void doSave(User user) {
addData1();
updateData2();
}
}