How to get transaction status from HibernateTransactionManager
I am trying to upgrade spring transaction manager from JtaTransactionManager to HibernateTransactionManager . The JTA TransactionManager has one method that gives the status of the current transaction. Based on the status, we do some operations. The implementation looks like this:
private void checkTransactionStatus(TransactionStatus status){
if(status instanceof DefaultTransactionStatus) {
DefaultTransactionStatus transactionStatus = (DefaultTransactionStatus) status;
if(transactionStatus.getTransaction() instanceof JtaTransactionObject){
JtaTransactionObject txObject = (JtaTransactionObject) transactionStatus.getTransaction();
int jtaStatus;
try {
jtaStatus = txObject.getUserTransaction().getStatus();
if(jtaStatus==Status.STATUS_MARKED_ROLLBACK){
// logic heare
}
} catch (SystemException e) {}
}
}
}
I want to replace this method with custom HibernateTransactionManager code. I analyzed and found that HibernateTransactionManager uses HibernateTransactionObject as transaction object. But unfortunately this is a private inner class that I cannot use to get the status. Then I tried using the parent class JdbcTransactionObjectSupport . But I don't know how to get the status from this parent class object.
private void checkTransactionStatus(TransactionStatus status){
if(status instanceof DefaultTransactionStatus) {
DefaultTransactionStatus transactionStatus = (DefaultTransactionStatus) status;
if(transactionStatus.getTransaction() instanceof JdbcTransactionObjectSupport){
JdbcTransactionObjectSupport txObject = (JdbcTransactionObjectSupport) transactionStatus.getTransaction();
//how to get the current status ?
}
}
}
source to share
Spring has a mechanism for accepting callbacks. You can implement the interface TransactionSynchronization
(or it is easier to extend TransactionSynchronizationAdapter
). You probably want to inject a method afterCompletion(int)
and put your logic there.
public class MyTxCallback extends TransactionSynchronizationAdapter {
public void afterCompletion(int status) {
if (status==STATUS_ROLLED_BACK) {
//logic here.
}
}
}
You can then link this to the transaction by calling TransactionSynchronizationManager
when the transaction starts. Now that the transaction is complete, the method is called and you can execute your logic (regardless of the underlying transaction resource used).
source to share
If you are using HibernateTransactionManager
, you can get the current state of the transaction from your Hibernate session:
LocalStatus status = session.getTransaction().getLocalStatus();
a LocalStatus
has the following states:
public enum LocalStatus {
/**
* The local transaction has not yet been begun
*/
NOT_ACTIVE,
/**
* The local transaction has been begun, but not yet completed.
*/
ACTIVE,
/**
* The local transaction has been competed successfully.
*/
COMMITTED,
/**
* The local transaction has been rolled back.
*/
ROLLED_BACK,
/**
* The local transaction attempted to commit, but failed.
*/
FAILED_COMMIT
}
source to share