Search code examples
javaspringhibernatejpatransactions

Hibernate 5 and Transaction rollback detection with interceptor


We had a Hibernate Interceptor that was intercepting afterTransactionCommit and checking the Transaction for wasCommited(), but we recently upgraded to Hibernate 5.0.7.Final, and hibernate 5 no longer has this call, and when we call the getStatus() function we only every seem to get either ACTIVE or NOT_ACTIVE regardless of the transaction state.

I looked at afterTransactionBegin and the transaction is marked ACTIVE, which is expected, and in beforeTransactionCompletion it is still marked ACTIVE, which again, is expected, but then in afterTransactionCommit it is marked NOT_ACTIVE, which doesn't make a sense to me. I would have expected one of COMMITTED, ROLLED_BACK, FAILED_COMMIT. I get this no matter if the transaction state, even if I throw an exception which causes a rollback, I still don't see any status other than NOT_ACTIVE.

The reason we are looking for this information is to determine if we need to post some messages to a queue. Basically if the transaction wasn't committed don't post. As of right now with Hibernate 5 I can't seem to find out how to determine programatically if the transaction was successful or not.


Solution

  • Hibernate 5 removed the ability to detect rollback in it's interceptor. Instead one can capture that transaction was rolled back and infer a rollback if it was not committed.

    For example:

    public class MyInterceptor extends EmptyInterceptor {
    .
    .
    .
    
    private static ThreadLocal<Boolean> wasCommited = new ThreadLocal();
    
    @Override
    public void beforeTransactionCompletion(Transaction tx) {
        // not called for rollback
        wasCommited.set(Boolean.TRUE);
    }
    
    
    @Override
    public void afterTransactionCompletion(Transaction tx) {
    
        if ( !Boolean.TRUE.equals(wasCommited.get()) ) {
            try {
               // handle transaction rolled back
            }
            finally {
                wasCommited.set(null);
            }
        }
    }
    }