Spring事务
1.1 前言
- spring对事务划分:分为单数据库事务和分布式事务(JTA),而单数据库事务中又根据具体API的不同,区分了datasource、hibernate、jpa、jdo下的事务管理实现。
- Spring事务传播行为:分为嵌套和独立事务,通过不同的传播行为配置,不同的业务方法可通过事务AOP的配置,实现开启新事务、作为嵌套事务或者加入当前事务等行为。
1.2 spring事务管理器
1.2.1 对象模型
spring中对事务的主要的抽象分为六个部分。
- TransactionDefinition:事务配置对象。包含事务的隔离级别、传播行为、超时等配置。
- TransactionObject:事务对象。包含connection连接对象等属性。
- TransactionStatus:事务上下文。包含当前事务对象、被挂起的事务等属性。
- transactionManager:事务管理器。主要事务的操作,事务的开启、挂起、恢复、提交和回滚。
- TransactionInterceptor:事务拦截器。用于事务的AOP实现。
- TransactionSynchronizationManager: 事务资源同步管理。主要包括事务只读、隔离,connection的属性。
1.2.1.1 TransactionDefinition
Spring调用方法时会读取事务相关属性
1.2.1.2 TransactionObject
此对象代表着从”jdbc事务API”这一段中可知,jdbc类型的不同事务一定包含有不同的connection.此外,由于事务传播行为的不同,每一个事务还需要需要两个状态分别标识这个事务是否需要回滚以及当前事务是否是活跃状态。
spring中DataSourceTransactionObject是datasource方式事务对象的实现,并通过父类中的ConnectionHolder来持有Connection对象以及标识事务的活跃及回滚状态。
1.2.1.3 TransactionStatus
事务上下文,包含了当前事务及当前事务相关配置信息,同时为了满足传播性,当事务挂起时,保存挂起事务相关信息(属性:suspendedResources,事务挂起),当当前事务执行完毕,会恢复挂起的事务。
1.2.1.4 transactionManager
事务管理器,事务管理器提供了事务的开启、提交、回滚、挂起、恢复等入口,获取事务时传入TransactionDefinition,返回事务上下文TransactionStatus;提交事务传入TransactionStatus,操作事务上下文;回滚事务,传入TransactionStatus,操作事务上下文。
1.2.1.5 TransactionInterceptor
继承自MethodInterceptor方法,项目启动实例化Bean时,会判断该Bean是否支持事务,如果有则会生成代理类;当调用该Bean方法时,代理类会执行的invoke方法。
1.2.1.6 TransactionSynchronizationManager
- resources:保存了数据源,与ConnectionHolder对象信息
- currentTransactionReadOnly:只读
- currentTransactionIsolationLevel:隔离级别
- actualTransactionActive:事务状态是否有事务
1.2.2 业务方法事务共享原理
- 开启事务的时候,先从TransactionSynchronizationManager中获取当前线程的connection对象,如果没有则创建事务,会将事务中connection对象放到TransactionSynchronizationManager。
- 操作数据库的时候,获取conection也从TransactionSynchronizationManager中获得连接资源,例如:mybatis与Spring整合,在SpringManagedTransaction.getConnectionDat()方法中利用DataSourceUtils获取连接信息,在DataSourceUtils中获取connection对象,如果开启事务,会从TransactionSynchronizationManager获取,否则从数据源中直接拿事务。
- 提交、回滚的时候,从TransactionSynchronizationManager获取connection对象进行数据库操作
1.3 事务处理流程
1.3.1 开启
时序图:
流程图:
获取事务:
完善事务子流程:
把事务记录保存到当前线程中子流程:
嵌套事务处理子流程:
1. 传播性为PROPAGATION_NEVER:直接抛出异常
2. 传播性为PROPAGATION_NOT_SUPPORTED:挂起原有的事务,将事务上下文transaction=null、newTransaction=false、suspendedResources=挂起的事务。
3. 传播性为PROPAGATION_REQUIRES_NEW:挂起原来的事务,将事务上下文
transaction=transaction、newTransaction=true、suspendedResources=挂起的事务。
4. 传播性为PROPAGATION_NESTED:调用步骤5。
5. 调用isNestedTransactionAllowed()方法,判断事务支持嵌套事务(JTA不支持),真步骤6,否则7。
6. 将事务上下文
transaction=transaction、newTransaction=false、suspendedResources=null,并设置savepoint属性。
7. 将事务上下文
transaction=transaction、newTransaction=true、suspendedResources=null。