JPA + Spring中异常后回滚事务

5

我正在使用Spring和JPA,底层是Hibernate。当抛出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;
}

但我收到了一个例外,说 javax.persistence.RollbackException: Transaction marked as rollbackOnly. 我知道当出现异常时需要回滚事务,但是如果我已经捕获了异常并且不想重新抛出它,那么如何回滚呢?

4个回答

7

通过在方法中使用@Transactional,如果出现任何RuntimeExceptions,它将自动执行回滚操作。您不需要手动执行此操作。您可能根本不应该捕获该异常,而是让它传递到更高级别的ExceptionHandler,以向用户显示一些标准错误页面(而不是堆栈跟踪)。另外,您的方法被标记为void,但您正在返回一个String。


谢谢,void只是一个打字错误,但我仍然遇到了RollbackException? - Tom Tucker
1
去掉try和catch怎么样?在我看来,你没有理由捕获和处理异常,因为你无法“修复”它。 - Robby Pond
实际上,我正在捕获一个约束违规,并尝试在用户用于提交数据的表单上显示本地化错误消息。 - Tom Tucker

5
你可以使用Spring的异常翻译和自定义的PersistenceExceptionTranslator来将PersistenceException转换为有用的信息。
顺便说一下,你不应该在DAO层使用@Transactional。事务应该在服务层启动。

2

看起来,Spring ORM 没有回滚失败的事务的方法。问题中显示的代码是一个服务类。将其持久化例程提取到单独的 DAO 类中,并让服务类处理 PersistenceExceptions 就可以解决问题。


0

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


实际上,@TomTucker,当事务被回滚时,异常将在调用数据访问异常的调用方法中捕获。在您的示例中,如果在事务回滚后抛出异常,则调用保存方法的方法将将其作为数据访问对象异常(DataAccessException)获取,并将此块放入调用方方法中,可以捕获异常并解析它并从中提取业务价值... - swati

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接