Spring supports programmatic transaction which give us fine grained control over TX management. According to Spring Documentation, One can use programmatic TX management by:
1. utilizing Spring's TransactionTemplate:
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
protected void doInTransactionWithoutResult(TransactionStatus status) {
try {
updateOperation1();
updateOperation2();
} catch (SomeBusinessExeption ex) {
status.setRollbackOnly();
}
} });
2. leveraging PlatformTransactionManager directly(inject a PlatformTransactionManager implementation into DAO):
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setName("SomeTxName");
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
//txManager is a reference to PlatformTransactionManager
TransactionStatus status = txManager.getTransaction(def);
try {
updateOperation1();
updateOperation2();
}
catch (MyException ex) {
txManager.rollback(status);
throw ex;
}
txManager.commit(status);
for the sake of simplification, let's say we are dealing with JDBC database operation.
I am wondering for any database operations happened at updateOperation1(),updateOperation2()
in the second snippet, either it is implemented with JDBCTemplate
or JDBCDaoSupport
, if not, the operation is actually not performed within any transaction, is it?
My analysis is that if we don't use JDBCTemplate
or JDBCDaoSupport
, we inevitably will create/retrieve connection from datasource management. the connection we get is of course not the connection used by PlatformTransactionManager
underlying to manage transaction.
I dug Spring source code and skim related class found that PlatformTransactionManager
will try to retrieve a connection contained in ConnectionHolder
which in return retrieved from TransactionSynchronizationManager
. I also found JDBCTemplate
and JDBCDaoSupport,
also try to get connection with similar routine from TransactionSynchronizationManager.
Because TransactionSynchronizationManager
manages many resource including connection per thread(basically use Threadlocal
to ensure one thread get its own unique instance of the managed resource)
So I think the connection retrieved by PlatformTransactionManager and JDBCTemplate
or JDBCDaoSupport
is just same, this can explain how spring programmatic transaction ensure updateOperation1(),updateOperation2()
were guarded by transaction.
Is my analysis correct? if it is, why Spring documentation hasn't emphasized this caveat?
Yes, it's correct.
Any code that uses raw Connection
s should obtain them from the DataSource
in special way in order to participate in transactions managed by Spring (12.3.8 DataSourceTransactionManager):
Application code is required to retrieve the JDBC connection through DataSourceUtils.getConnection(DataSource) instead of Java EE's standard DataSource.getConnection.
Another option (if you cannot change code that calls getConnection()
) is to wrap your DataSource
with TransactionAwareDataSourceProxy
.
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