Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Roll back transaction after exception in JPA + Spring

I'm using Spring and JPA with HIbernate underneath. 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.

@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. 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?

like image 734
Tom Tucker Avatar asked Feb 22 '11 19:02

Tom Tucker


People also ask

Does transaction rollback on exception?

RollbackException exception is thrown when the transaction has been marked for rollback only or the transaction has been rolled back instead of committed. This is a local exception thrown by methods in the UserTransaction , Transaction , and TransactionManager interfaces.

How do I roll back a JPA transaction?

To rollback a transaction you can use @Transaction annotation. You can either implement it on method level or class level. Class level @Transactional(rollbackFor = Exception.

Which attribute of @transactional can be used to rollback the operations when a exception of exception type is raised thrown within the method?

So if you throw an Exception or a subclass of it, always use the above with the @Transactional annotation to tell Spring to roll back transactions if a checked exception occurs.

Which of these by default will cause the rollback of the Spring transaction?

By default, the only exceptions that cause a transaction to roll back are the unchecked exceptions (like RuntimeException ).


3 Answers

By using @Transactional if there are any RuntimeExceptions thrown in the method, it will automatically perform the rollback. 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). Also your method is marked void but you are returning a String.

like image 191
Robby Pond Avatar answered Sep 29 '22 00:09

Robby Pond


You can use Spring's Exception Translation with a custom PersistenceExceptionTranslator to translate PersistenceException into something useful.

Oh, btw, you shouldn't use @Transactional at the DAO level. Transactions should be started at the service level.

like image 22
Sean Patrick Floyd Avatar answered Sep 28 '22 22:09

Sean Patrick Floyd


It appears that there is no way to roll back a failed transaction managed by 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.

like image 43
Tom Tucker Avatar answered Sep 29 '22 00:09

Tom Tucker