【发布时间】:2017-12-04 12:10:21
【问题描述】:
我正在实现一个 JDBC 数据库访问 API(基本上是一个包装器),我使用 Spring JdbcTemplate 和 PlatformTransactionManager 来处理事务操作。一切看起来都不错,但我无法理解 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