事务执行原理
入口是invokeWithinTransaction,能走到这一步,说明已经在代理类那里经过过滤,方法头上使用了Transaction注解。
首先取到注解上的参数,保存到TransactionAttribute的子类中,之后,取到TransactionManager;
调用createTransactionIfNecessary方法,基于前面解析出来的Transaction注解配置参数判断是否需要创建事务,如需要则创建,默认事务的名称是当前执行方法的名称。
首先调用doGetTransaction方法获取当前存在的事务信息,这里是基于当前的datasource从threadlocal对象resources中获取当前的conn,之后封装成DataSourceTransactionObject对象返回,除了嵌套调用的事务,一般这里取到的都是null。
之后判断是否有取到connection对象,根据是否有事务决定下一步策略,这里的策略是由当前的事务传播机制确定的。
- 之前已经存在了事务 进入handleExistingTransaction方法处理 判断传播机制
- PROPAGATION_NEVER(不允许当前线程存在事务) 直接报错
- PROPAGATION_NOT_SUPPORTED(当前方法中不支持事务) 因为当前方法不需要事务,所以直接把前面的事务挂起,之后保存当前的事务状态,事务对象为null
- PROPAGATION_REQUIRES_NEW 挂起之前的事务 开启新的事务
- PROPAGATION_NESTED(父子事务) 这里有一个概念是savepoint,如果这里创建的事务要回滚,则回滚到这个savepoint
- 之前不存在事务 判断传播机制
- PROPAGATION_MANDATORY 直接报错,因为这个传播机制要求当前一定要有事务存在
- PROPAGATION_REQUIRED(默认传播机制,要求存在事务,如没有则新建,有的话则不用关心)
- PROPAGATION_REQUIRES_NEW(要求必须创建一个新的事务)
- PROPAGATION_NESTED(要求创建父子事务) 以上三种情况下,都会去调用startTransaction创建一个新的事务。 首先在使用suspend方法初始化当前的事务信息,这里suspend方法的作用是,如果有传入事务对象,则挂起之前的事务,并设置到当前事务信息中,同时初始化当前的事务信息,这里调用suspend是用的初始化当前事务信息的功能。 之后doBegin方法中基于构建好的definition初始化事务对象:
- 创建数据库连接对象,并设置连接对象的readonly属性以及事务的隔离级别
- 将conn对象的AutoCommit属性设置为false
- 将第一步创建好的conn对象绑定到前面的threadlocal中,方便后面获取
*这里有一点,在mybatis执行sql操作的时候,首先就是从这里取conn,如果有,并且SynchronizedWithTransaction为true,则使用。
到这一步就已经基于不同的情况取到了当前的事务对象,下一步要做的是把当前的事务信息绑定到threadlocal对象中,方便后面获取。
之后做的是如果捕捉到了异常,就处理事务回滚。
所有事情都处理完之后,在finally块中清除当前线程中的事务信息。
最后提交当前事务。
Original: https://www.cnblogs.com/guoweishi/p/16566726.html
Author: sunnysgw
Title: spring 事务
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/592304/
转载文章受原作者版权保护。转载请注明原作者出处!