不支持SpringBoot 2事务传播嵌套

时间:2018-08-08 14:05:36

标签: java spring hibernate spring-boot spring-data-jpa

我有一个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传播,我如何实现我的目标?

1 个答案:

答案 0 :(得分:0)

我建议您将它们分解为两个独立的交易。

在第一个事务中,执行firstServiceMethod中当前您要提交的所有工作。 (例如,通过saveAndFlush)。现在,当您退出此方法时,更改将被提交,因此它们可用于后续调用。

然后用名为firstServiceMethod的对象调用新的事务处理方法setFirstEntityStatus(),该方法调用secondServiceMethod并适当地设置实体的状态。

基本上,而不是尝试嵌套事务,将它们分为两个完全独立的事务,并使用顺序来确保第一个结果可用于第二个。