Spring Boot:在请求解析之前回滚事务

时间:2017-02-07 18:51:24

标签: spring hibernate jpa spring-boot transactions

我的服务类中有一个方法,它对一个实体执行一些更改,之后它执行一些关键代码(与不同微服务的通信),这些代码可能会返回附加到异常的错误信息。如果发生错误,则应还原更改。为了达到这个目的,我想我会使用@Transactional。

服务

@Service
public class MyService {
    @Autowired
    private EntityRepository repository;

    @Transactional(rollbackFor = CriticalCodeException.class, isolation = Isolation.READ_COMMITTED, propagation = Propagation.NESTED)
    public Entity foo(entity) {
        /* perform changes ... */
        entity.setBar(...) 
        try {
            /* critical code */
        } catch (CriticalCodeException e) {
            e.setEntityId(entity.getId());
            throw e;
        }
    }

    public attachError(CriticalCodeException e) {
        // reload entity which should be rolled back but is not
        Entity reloaded = repository.findOne(e.getEntityId);
        reloaded.setError(e.getError); // attach error
        repository.save(reloaded)  // saves changes which should be rolled back
    }
}

由于CriticalCodeException是一个RuntimeException,也可能发生在另一个上下文中,我创建了一个指定的ExceptionHandler,它应该捕获它并将错误附加到我的实体。

的ExceptionHandler

@ExceptionHandler(CriticalCodeException .class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ErrorResponse processError(CriticalCodeException e) {
    entityService.attachError(e);
    return e.getError();
}

然而,当我附上错误时,我也不会挽救过去的改变。因此,当我从嵌套的@Transactional方法抛出Exception之后重新加载实体时,我希望它处于初始状态。嗯,事实并非如此。如果我没有附加错误(因此省略我的save()调用),则更改不会持久化。所以我认为在我的异常处理之后最终会执行回滚。

在回滚完成后,有人能告诉我如何在初始状态下访问我的实体吗?

我正在使用JPA和Hibernate的Spring Boot Data。我已尝试使用@EnableTransactionManagement等各种配置并设置不同的bean组合。然而,经过大量的研究,我非常肯定@Transactional实际上正在工作(从上面描述的最终回滚中可以看出),并且无需进一步配置即可工作。我做错了什么?

修改

事实上,这些变化已经回滚,但我的实体经理没有被重置,只有M. Deinum指出。在我的持久性设置中,对实体的更改仅通过调用repository.save(entity)来保留。我最终做的是省略事务方法,而是实现repository.reload(entity),它通过实体管理器刷新我的实体。通过这种方式,我可以摆脱以前所做的更改,这些更改甚至不会在第一时间持续存在。

0 个答案:

没有答案