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