我有一个 SpringBoot 2 项目,我正在使用带有休眠的 Spring data jpa 和 MySQL5.7
我在以下用例中遇到问题:我有一个调用另一个服务方法的服务方法。如果第二个服务的方法生成运行时异常,则第一个方法也会标记为回滚,我无法再提交内容。我只想回滚第二种方法,并且仍然在第一种方法中提交一些东西。
我尝试使用传播。嵌套但嵌套事务不允许使用休眠(即使jpaTransactionManager支持它们并且MySQL支持保存点(。
我该如何解决这个问题?我可以以某种方式配置嵌套吗?
请记住,我需要第二种方法来查看第一个提交的更改,因此我无法将第二种方法标记为传播。REQUIRES_NEW
这是澄清我的问题的示例代码:
第一服务.java
@Service
public class FirstServiceImpl implements FirstService
@Autowired
SecondService secondService;
@Autowired
FirstServiceRepository firstServiceRepository;
@Transactional
public void firstServiceMethod() {
//do something
...
FirstEntity firstEntity = firstServiceRepository.findByXXX();
firstEntity.setStatus(0);
firstServiceRepository.saveAndFlush(firstEntity);
...
boolean runtimeExceptionHappened = secondService.secondServiceMethod();
if (runtimeExceptionHappened) {
firstEntity.setStatus(1);
firstServiceRepository.save();
} else {
firstEntity.setStatus(2);
firstServiceRepository.save();
}
}
第二服务.java
@Service
public class SecondServiceImpl implements SecondService
@Transactional
public boolean secondServiceMethod() {
boolean runtimeExceptionHappened = false;
try {
//do something that saves to db but that may throw a runtime exception
...
} catch (Exception ex) {
runtimeExceptionHappened = true;
}
return runtimeExceptionHappened;
}
所以问题是当 secondServiceMethod(( 引发运行时异常时,它会回滚其操作(没关系(,然后将其返回变量 runtimeExceptionHappen 设置为 false,但随后 firstServiceMethod 被标记为仅回滚,然后
firstEntity.setStatus(1);
firstServiceRepository.save();
未提交。
由于我无法使用嵌套传播,我该如何实现我的目标?
我建议你把它们分成两个单独的事务。
在第一个事务中,以您知道要提交的firstServiceMethod
执行当前的所有工作。(例如,通过保存和冲洗(。现在,当您退出此方法时,将提交更改,因此它们将可用于后续调用。
然后,让调用firstServiceMethod
调用新的事务方法setFirstEntityStatus()
该方法调用secondServiceMethod
并根据需要设置实体的状态。
基本上,与其尝试 NEST 事务,不如将它们拆分为两个完全独立的事务,并使用排序来确保第一个的结果可供第二个可用。