我有一个SpringBoot 2项目,并且我在Spring5.7和Hibernate中使用spring data jpa
我在以下用例中遇到问题:我有一个调用另一个服务方法的服务方法。如果第二个服务的方法生成运行时异常,则第一个方法也将标记为回滚,并且我无法再提交任何东西。我只想回滚第二个方法,并且仍然在第一个方法中提交一些内容。
我试图使用propagation.nested,但是休眠状态不允许嵌套事务(即使jpaTransactionManager支持它们并且MySQL支持保存点)。
我该如何解决这个问题?我可以通过某种方式配置嵌套吗?
请记住,我需要第二种方法来查看第一种方法提交的更改,因此我无法将第二种方法标记为“传播”。REQUIRES_NEW
以下是示例代码来阐明我的问题:
FirstServiceImpl.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();
}
}
SecondServiceImpl.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()引发运行时异常时,它将回滚其操作(这样就可以了),然后将其返回变量runtimeExceptionHappened设置为false,但是将firstServiceMethod标记为仅回滚,然后
firstEntity.setStatus(1);
firstServiceRepository.save();
未提交。
由于我无法使用NESTED传播,我如何实现我的目标?
答案 0 :(得分:0)
我建议您将它们分解为两个独立的交易。
在第一个事务中,执行firstServiceMethod
中当前您要提交的所有工作。 (例如,通过saveAndFlush)。现在,当您退出此方法时,更改将被提交,因此它们可用于后续调用。
然后用名为firstServiceMethod
的对象调用新的事务处理方法setFirstEntityStatus()
,该方法调用secondServiceMethod
并适当地设置实体的状态。
基本上,而不是尝试嵌套事务,将它们分为两个完全独立的事务,并使用顺序来确保第一个结果可用于第二个。