Spring程序化事务管理需要注意什么?

时间:2012-06-18 17:22:38

标签: java spring transactions

Spring支持程序化事务,它使我们能够对TX管理进行细致的控制。根据Spring Documentation,可以通过以下方式使用程序化TX管理:
1.利用Spring的TransactionTemplate:

transactionTemplate.execute(new TransactionCallbackWithoutResult() {

protected void doInTransactionWithoutResult(TransactionStatus status) {
    try {
        updateOperation1();
        updateOperation2();
    } catch (SomeBusinessExeption ex) {
        status.setRollbackOnly();
    }
} });

2。直接利用PlatformTransactionManager(将一个PlatformTransactionManager实现注入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);

为简化起见,假设我们正在处理JDBC数据库操作。

我想知道第二个代码段中updateOperation1(),updateOperation2()发生的任何数据库操作,是用JDBCTemplate还是JDBCDaoSupport实现的,如果没有,操作实际上不在任何内容中执行交易,是吗?

我的分析是,如果我们不使用JDBCTemplateJDBCDaoSupport,我们将不可避免地从数据源管理创建/检索连接。我们得到的连接当然不是PlatformTransactionManager底层用来管理事务的连接。

我挖了Spring源代码并略读相关类,发现PlatformTransactionManager将尝试检索ConnectionHolder中包含的连接,该连接从TransactionSynchronizationManager检索回来。我还发现JDBCTemplateJDBCDaoSupport,也尝试与TransactionSynchronizationManager.

中的类似例程建立联系

因为TransactionSynchronizationManager管理许多资源,包括每个线程的连接(基本上使用Threadlocal来确保一个线程获得自己的托管资源的唯一实例)

所以我认为PlatformTransactionManager和JDBCTemplateJDBCDaoSupport检索的连接是一样的,这可以解释spring programmatic事务如何确保updateOperation1(),updateOperation2()被事务保护。

我的分析是否正确?如果是的话,为什么Spring文档没有强调这个警告呢?

1 个答案:

答案 0 :(得分:3)

是的,这是对的。

使用原始Connection的任何代码都应以特殊方式从DataSource获取它们,以便参与Spring管理的事务(12.3.8 DataSourceTransactionManager):

  

需要应用程序代码来通过DataSourceUtils.getConnection(DataSource)而不是Java EE的标准DataSource.getConnection来检索JDBC连接。

另一个选项(如果您无法更改调用getConnection()的代码)是用TransactionAwareDataSourceProxy包裹DataSource