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.
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);
}
}
}
}
If you use Spring transaction, you can use a TransactionSynchronization for this kind of things. For example :
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization(){
void afterCommit() {
..
}
});
See TransactionSynchronizationManager
I successfully utilized javax.transaction.Synchronization which can be registered with the transaction and receives correct status. It can be registered using the Hibernate Interceptor:
@Override
public void afterTransactionBegin(Transaction tx) {
tx.registerSynchronization(new Synchronization() {
@Override
public void afterCompletion(int status) {
// Here the status is correct
}
});
}
Edit:
Unfortunattely, this solution works only, if the commit or rollback succeedes, otherwise the callback is not called. I must have had wrong test initially. You can see that in the code of JdbcResourceLocalTransactionCoordinatorImpl.TransactionDriverControlImpl.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With