【问题标题】:Spring programmatic transaction management caveat?Spring程序化事务管理警告?
【发布时间】:2012-06-18 17:22:38
【问题描述】:

Spring 支持程序化事务,这使我们能够对 TX 管理进行细粒度控制。根据 Spring 文档,可以通过以下方式使用程序化 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 数据库操作。

我想知道在第二个sn-p中updateOperation1(),updateOperation2()发生的任何数据库操作,是用JDBCTemplate还是JDBCDaoSupport实现的,如果不是,该操作实际上不是在任何事务中执行的,是吗?

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

我挖掘了 Spring 源代码并浏览了相关类,发现 PlatformTransactionManager 将尝试检索包含在 ConnectionHolder 中的连接,而该连接又从 TransactionSynchronizationManager 检索。我还发现JDBCTemplateJDBCDaoSupport, 也尝试与TransactionSynchronizationManager. 的类似例程建立联系

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

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

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

【问题讨论】:

    标签: java spring transactions


    【解决方案1】:

    是的,没错。

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

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

    另一种选择(如果您无法更改调用getConnection() 的代码)是将DataSource 包装为TransactionAwareDataSourceProxy

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-06-12
      • 1970-01-01
      • 2015-07-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多