说明如何用 spring 进行事务管理和 spring 如何实现事务
spring 事务中的概念
事务定义 TransactionDefinition
定义 spring 事务的属性- 隔离等级(Isolation Level),控制本事务与其他事务的隔离级别
- ISOLATION_DEFAULT
- ISOLATION_READ_UNCOMMITTED
- ISOLATION_READ_COMMITTED
- ISOLATION_REPEATABLE_READ
- ISOLATION_SERIALIZABLE
- 传播行为(Propagation Behavior),表示由一个事务控制的方法调用另一个事务控制的方法时的行为
- PROPAGATION_REQUIRED,如果当前有事务,就加入当前事务;如果没有,则打开一个新事务
- PROPAGATION_SUPPORTS,如果当前有事务,就加入当前事务;如果没有,就以非事务方式执行
- PROPAGATION_MANDATORY,如果当前有事务,就加入当前事务;如果没有就抛出异常
- PROPAGATION_REQUIRES_NEW,如果当前有事务,就挂起当前事务,然后开启新事务
- PROPAGATION_NOT_SUPPORTED,总是以非事务方式执行,如果当前有事务,就挂起
- PROPAGATION_NEVER,总是以非事务方式执行,如果当前有事务,就抛出异常
- PROPAGATION_NESTED,如果当前有事务,就在嵌套事务内执行;如果没有就打开一个新事务
- 超时(Timeout),单位是秒
- 是否只读(Read Only)
- 隔离等级(Isolation Level),控制本事务与其他事务的隔离级别
事务状态 TransactionStatus
表示一个事务的状态事务管理器 PlatformTransactionManager
用来操作事务和管理事务,有以下操作- TransactionStatus getTransaction(TransactionDefinition definition) 返回当前事务或开启新事务
- void commit(TransactionStatus status) 提交事务
- void rollback(TransactionStatus status) 回滚事务
spring 事务的使用方式
编程式事务
使用 TransactionTemplate 或者直接使用底层的 PlatformTransactionManager (不推荐), 这种方式比较少使用
1 | TransactionTemplate t = new TransactionTemplate(); |
基于注解的声明式事务
用 @Transactional 注解标记类或方法,然后 spring 会在事务中执行方法
1 | (rollbackFor = Throwable.class) |
@Transactional 有如下属性:
- value: transactionManager 的别名
- transactionManager: 指定的事务管理器
- propagation:事务传播行为
- isolation:事务隔离级别
- timeout:超时值
- readOnly:是否只读
- rollbackFor:表示哪些异常抛出时会回滚事务
- rollbackForClassName:同上
- noRollbackFor:表示哪些异常抛出时不会回滚事务
- noRollbackForClassName:同上
基于 XML 配置的声明式事务
XML 方式是基于 tx 和 aop 名字空间的标签定义一个事务增强器
1 | <tx:advice id="advice" transaction-manager="transactionManager"> |
基于 TransactionProxyFactoryBean 的声明式事务
定义一个 TransactionProxyFactoryBean 单独为某些 bean 增加事务增强
1 |
|
spring 事务的实现
事务同步
TransactionSynchronizationManager,实现事务的关键类,用于实现资源管理。资源管理,是对那些应该一个资源只在一个线程中使用的(如 JDBC Connections 和 Hibernate Sessions)资源进行管理。这类资源通常不会假设对线程进行绑定,所以进行事务管理时就需要这个操作。
1 |
|
事务的实现
spring 事务支持对不同的资源进行管理,它由 AbstractPlatformTransactionManager 实现,不同的资源需要继承 AbstractPlatformTransactionManager 然后覆写一些关键方法,从而实现对不同资源的事务管理。例如 jdbc 事务的实现是 DataSourceTransactionManager。
1 | public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable { |
jdbc 事务
要实现 jdbc 事务,需要保证在同一个线程中获取的都是同一个 Connection。 使用 DataSourceUtils.getConnection 方法可以获取 Connection。 DataSourceUtils.getConnection 会尝试用 TransactionSynchronizationManager.getResource 来事务里的 Connection。如果在一个事务里,TransactionSynchronizationManager.getResource 将返回之前的 ConnectionHolder,可以从中获取 Connection;如果不在一个事务里,TransactionSynchronizationManager.getResource 返回 null,这时 DataSourceUtils.getConnection 就从 DataSource 获取 Connection。
1 |
|
事务需要事务管理器来管理,JDBC 事务由 DataSourceTransactionManager 类实现,它是 AbstractPlatformTransactionManager 的子类,主要是实现 AbstractPlatformTransactionManager 里定义的抽象方法
1 | public class DataSourceTransactionManager extends AbstractPlatformTransactionManager |
声明式事务的实现
不论是用注解还是用 XML 方式,都是使用 AOP 实现事务,通过 TransactionInterceptor 来进行事务功能的增强
1 | public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable { |