上回说到,直接使用JDBC操作数据库增删改查是非常繁琐的,因此Spring提供了模板类(JdbcTemplate
, NamedParameterJdbcTemplate
)来简化我们和数据库的交互。同样的,直接使用JDBC进行事务的关系也需要写很多非业务代码,Spring提供了一个接口来完成事务的提交和回滚等功能,即接口PlatformTransactionManager
,如果是使用jdbc则使用DataSourceTransactionManager
来完成事务的提交和回滚,如果是使用hibernate则使用HibernateTransactionManager来完成事务的提交和回滚。
事务的定义接口为TransactionDefinition
,它有两个重要的属性,事务的传播属性和隔离级别:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23public interface TransactionDefinition {
int PROPAGATION_REQUIRED = 0;
int PROPAGATION_SUPPORTS = 1;
int PROPAGATION_MANDATORY = 2;
int PROPAGATION_REQUIRES_NEW = 3;
int PROPAGATION_NOT_SUPPORTED = 4;
int PROPAGATION_NEVER = 5;
int PROPAGATION_NESTED = 6;
int ISOLATION_DEFAULT = -1;
int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED;
int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED;
int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ;
int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE;
int TIMEOUT_DEFAULT = -1;
int getPropagationBehavior();
int getIsolationLevel();
int getTimeout();
boolean isReadOnly();
String getName();
}
DefaultTransactionDefinition
是对上述属性设置的一些默认值,传播属性默认为PROPAGATION_REQUIRED
,隔离级别默认为ISOLATION_DEFAULT
,采用的是底层数据库采用的默认隔离级别。
TransactionAttribute
接口:
1 | public interface TransactionAttribute extends TransactionDefinition { |
DefaultTransactionAttribute
:
1 | public boolean rollbackOn(Throwable ex) { |
TransactionTemplate使用示例
首先新建DataSourceTransactionManager
的bean:
1 |
|
然后新建TransactionTemplate
:
1 |
|
看一下TransactionTemplate
的使用示例:
1 | public String addUserWithTransaction(User user) { |
TransactionTemplate原理
1 | public <T> T execute(TransactionCallback<T> action) throws TransactionException { |
首先调用DataSourceTransactionManager.getTransaction
方法获取事务状态:
DataSourceTransactionManager.getTransaction
getTransaction方法处理传播行为
1 | public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException { |
首先调用DataSourceTransactionManager.doGetTransaction
。
doGetTransaction
方法返回一个事务对象,表示当前的事务状态。该对象通常是具体事务管理的实现,以可修改的方式携带相应的事务状态。该对象将被直接或作为DefaultTransactionStatus
实例的一部分传递给其他模板方法(例如:doBegin和doCommit)。
返回的对象应包含有关任何现有事务的信息,即事务管理器上当前调用getTransaction
之前已经开始的事务。因此,doGetTransaction
实现通常会查找现有的事务,并在返回的事务对象中存储对应的状态。
1 | protected Object doGetTransaction() { |
TransactionSynchronizationManager.getResource
:
1 | public static Object getResource(Object key) { |
handleExistingTransaction
回到getTransaction
方法,调用isExistingTransaction
判断是否已经存在事务,如果已经存在则调用handleExistingTransaction
。
1 | private TransactionStatus handleExistingTransaction( |
doBegin
回到getTransaction
方法,如果当前没有事务,且传播行为是PROPAGATION_REQUIRED
、PROPAGATION_REQUIRES_NEW
、PROPAGATION_NESTED
其中一种,则新建一个事务并执行。
1 | protected void doBegin(Object transaction, TransactionDefinition definition) { |
commit
回到execute
方法,获取事务状态后调用doInTransaction
执行用户的代码。
如果用户的代码没有抛出异常,则调用AbstractPlatformTransactionManager.commit
提交事务,
1 | public final void commit(TransactionStatus status) throws TransactionException { |
rollbackOnException
如果用户的代码抛出异常,则调用rollbackOnException
-> processRollback
-> doRollback
回滚,