简体   繁体   English

在JPA + Spring中异常后回滚事务

[英]Roll back transaction after exception in JPA + Spring

I'm using Spring and JPA with HIbernate underneath. 我正在使用Spring和JPA以及HIbernate。 When a PersistenceException is thrown, I want to catch it and return the error message so that it is not propagated up to the caller. 抛出PersistenceException时,我想捕获它并返回错误消息,以便它不会传播到调用者。

@Transactional
public String save(Object bean) {
    String error = null;

    try {
        EntityManager entityManager = getEntityManager();

        for (int i = 0, n = entities.size(); i < n; i ++) {
            entityManager.merge(entities.get(i));
        }
    }
    catch (PersistenceException e) {
        error = e.getMessage();
    }

    return error;
}

But I get an exception saying that javax.persistence.RollbackException: Transaction marked as rollbackOnly. 但我得到一个例外,说javax.persistence.RollbackException: Transaction marked as rollbackOnly. I get that the transaction needs to be rolled back after an exception but how do I roll it back when I've catched the exception and do not want to re-throw it? 我知道事务需要在异常后回滚,但是当我捕获异常并且不想重新抛出异常时如何将其回滚?

By using @Transactional if there are any RuntimeExceptions thrown in the method, it will automatically perform the rollback. 如果方法中抛出任何RuntimeExceptions,则使用@Transactional ,它将自动执行回滚。 You don't need to manually do it. 您无需手动执行此操作。 You probably shouldn't be catching that exception at all and instead let it pass to a higher level ExceptionHandler that shows some standard error page to the user (not the stack trace). 您可能根本不应该捕获该异常,而是让它传递给更高级别的ExceptionHandler,它向用户显示一些标准错误页面(而不是堆栈跟踪)。 Also your method is marked void but you are returning a String. 此外,您的方法标记为void,但您返回的是String。

You can use Spring's Exception Translation with a custom PersistenceExceptionTranslator to translate PersistenceException into something useful. 您可以使用Spring的Exception Translation和自定义PersistenceExceptionTranslatorPersistenceException转换为有用的东西。

Oh, btw, you shouldn't use @Transactional at the DAO level. 哦,顺便说一句,你不应该在DAO级别使用@Transactional Transactions should be started at the service level. 交易应该在服务级别开始。

It appears that there is no way to roll back a failed transaction managed by Spring ORM. 似乎没有办法回滚Spring ORM管理的失败事务。 The code shown in the question is a service class. 问题中显示的代码是服务类。 Extracting its persistence routine to a separate DAO class and having the service class handle PersistenceExceptions did the trick. 将其持久性例程提取到单独的DAO类并使服务类处理PersistenceExceptions就可以了。

对抛出异常的方法使用@Transactional(noRollbackFor={PersistenceException.class})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM