【问题标题】:Spring PlatformTransactionManager - concurrent transactionsSpring PlatformTransactionManager - 并发事务
【发布时间】:2017-12-04 12:10:21
【问题描述】:

我正在实现一个 JDBC 数据库访问 API(基本上是一个包装器),我使用 Spring JdbcTemplatePlatformTransactionManager 来处理事务操作。一切看起来都不错,但我无法理解 jdbcTemplate 如何管理并发事务。 我将根据学生的创建给你一个简化的例子来说明我的观点。让我们创建 2 个学生,John 和 Jack。第一个没有错误,第二个有错误,步骤和代码如下。

  • John 开始交易
  • 执行 John 插入而不提交
  • 等待 Jack 插入
  • Jack 开始交易
  • 执行 Jack 插入时出错(年龄为空,但需要数据库非 - 空)
  • 回滚 Jack 交易
  • 提交 John 事务

StudentDAO

public class StudentJDBCTemplate implements StudentDAO {

   private DataSource dataSource;
   private JdbcTemplate jdbcTemplateObject;
   private PlatformTransactionManager transactionManager;

   // constructor, getters and setters

  public TransactionStatus startTransaction() throws TransactionException {
      TransactionDefinition def = new DefaultTransactionDefinition();
      transactionManager.getTransaction(def);
  }

  public void commitTransaction(TransactionStatus status) throws TransactionException {
      transactionManager.commit(status);
  }

  public void rollbackTransaction(TransactionStatus status) throws TransactionException {
      transactionManager.rollback(status);
  }

   public void create(String name, Integer age){
      String SQL1 = "insert into Student (name, age) values (?, ?)";
      jdbcTemplateObject.update( SQL1, name, age);
      return;
   }
}

主应用程序

public class MainApp {
    public static void main(String[] args){
        // setup db connection etc

       StudentJDBCTemplate studentDao = new StudentJDBCTemplate();

       TransactionStatus txJohn = studentDao.startTransaction();
       TransactionStatus txJack = studentDao.startTransaction();

       studentDao.create("John", 20);

       try {
           studentDao.create("Jack", null); // **FORCE EXCEPTION**
       } catch(Exception e){
           studentDao.rollback(txJack);
       }
       studentDao.commit(txJohn);
    }
}

JdbcTemplate 如何知道 1 笔交易可以,而另一笔不能?据我了解,尽管我们创建了 2 个事务,JdbcTemplate 将回滚 Jack AND John 事务,因为查询、执行和更新方法不需要 TransactionStatus 作为参数。那就是说Spring jdbcTemplate一次只支持1个事务?!

【问题讨论】:

  • 事务是基于线程的,你有 2 个线程,每个线程都有自己的状态。
  • 我已经更新了示例,请检查。现在我只有一个线程,jdbcTemplate 如何知道要在 studentDao.create 调用上使用哪个事务?
  • 您的示例使用单个事务而不是 2。第二次调用 startTransaction 将返回已经进行的事务的状态。如果您启用调试日志记录,您将看到第二次启动会产生一条调试消息,说明您正在参与正在进行的事务。如果使用REQUIRES_NEW 指定这样做,它只会启动一个新事务,否则只有一个事务。如果使用多个线程,则只能有多个事务。
  • 好的,现在更有意义了。所以你告诉我的是我可以有多个线程引用同一个DAO(在这种情况下是StudentJDBCTemplate)并且每个查询/更新/等执行都将属于一个单独的事务,因为我们在线程的开头调用getTransaction对吧?

标签: java spring concurrency transactions jdbctemplate


【解决方案1】:

单个事务中的所有操作始终作为一个单元执行,因此要么全部提交,要么不提交。

如果 John 启动一个插入然后更新的事务,则要么(插入和更新)都成功,要么都不成功,并且不会受到 Jack 发起的事务的影响。

现在并发事务如何相互干扰由隔离级别控制,即一个事务如何看待另一个并发事务修改的数据。

【讨论】:

  • 但是 jdbcTemplate 如何知道 update(SQL1, name, age) 在 John 或 Jack 事务中?
  • 当 Jack 和 John 使用不同的参数提交相同的表单时,这个概念是相同的。服务器使用单独的线程来处理每个请求。
  • 还是不回答我的问题。我已经更新了示例,请检查。现在我只有一个线程,jdbcTemplate 如何知道必须在 studentDao.create 调用上使用哪个事务
猜你喜欢
  • 2015-09-19
  • 1970-01-01
  • 1970-01-01
  • 2013-09-10
  • 1970-01-01
  • 2023-03-18
  • 2020-05-29
  • 2011-07-05
  • 2016-11-03
相关资源
最近更新 更多