spring--mybatis事务总结

spring--事务原理mybatis--MapperScannerConfigurer 和 mybatis--MapperProxy事务,最近想把spring mybatis中的事务和mapper接口的原理分析分析,陆陆续续写了些,这篇做个总结。

spring+mybatis mapper接口 声明式事务配置

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"
      lazy-init="false">
    <property name="dataSource" ref="dataSource"/>
    <property name="mapperLocations" value="classpath:sqlmapper/*Mapper.xml"/>
    <property name="plugins">
        <list>
            <bean class="***">
                <property name="dialect">
                    <bean class="***"/>
                </property>
            </bean>
        </list>
    </property>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="*.*.*" />
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
    </bean>

<bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="do*" read-only="false" rollback-for="java.lang.Exception"/>
            <tx:method name="*" propagation="SUPPORTS" read-only="true"/>
        </tx:attributes>
    </tx:advice>

    <aop:config>
        <aop:pointcut id="pc" expression="execution(* springtry.web.service.*.*(..))"/>
        <aop:advisor pointcut-ref="pc" advice-ref="txAdvice"/>
    </aop:config>

ps:以上在service层注入事务,do开头方法传播机制是required,其它的是supports

1. org.mybatis.spring.SqlSessionFactoryBean解析mapper xml配置,根据namespace添加class mapper组装Configuration对象,设置它的environment(包含springManagedTransactionFactory),最后getObject()包装出DefaultSqlSessionFactory;

2. org.mybatis.spring.mapper.MapperScannerConfigurer扫描basePackage下的mapper接口,每个接口封装为MapperFactoryBean(包含封装了DefaultSqlSessionFactory的SqlSessionTemplate),注册给spring容器。

ps:当调用"mapper接口"时去DefaultSqlSessionFactory-》Configuration获得接口类的代理类

MapperProxy mapperProxy = new MapperProxy(sqlSession, this.mapperInterface, this.methodCache);

3. 前面两步是系统的前提工作。

从service层方法开始,首先进入TransactionInerceptor事务拦截器,由 DataSourceTransactionManager 生成一个DataSourceTransactionObject事务对象,封装在DefaultTransactionStatus中,调用doBegin开启这个事务对象,设置这个事务对象 setConnectionHolder(new ConnectionHolder(Connection ex)),把这个ConnectionHolder 以键值对绑定在当前线程上 <this.getDataSource(),txObject.getConnectionHolder()>

TransactionSynchronizationManager.bindResource(this.getDataSource(), txObject.getConnectionHolder());

返回这个 DefaultTransactionStatus对象,封装在TransactionAspectSupport.TransactionInfo中,绑定在当前线程上,之后调用实际service方法

4. service方法中会注入mybatis mapper接口,调用时实际调用

MapperFactoryBean-》SqlSessionTemplate-》DefaultSqlSessionFactory-》Configuration.getMapper(mapper接口, SqlSessionTemplate);

 返回MapperProxy对mapper接口的代理,接着调用MapperProxy

5. MapperProxy中,根据调用的Method返回一个MapperMethod对象.execute(SqlSessionTemplate this.sqlSession, args),其中调用sqlSession.insert,           sqlSession.update,sqlSession.delete,sqlSession.selectList,sqlSession.selectMap,sqlSession.selectOne等,

6. 接下来调用SqlSessionTemplate的方法,实际调用SqlSessionTemplate.sqlSessionProxy(SqlSessionTemplate.SqlSessionInterceptor拦截器拦截的代理),拦截器中使用 SqlSessionUtils 调用

SqlSessionTemplate.DefaultSqlSessionFactory.openSession-》Configuration-》environment-》springManagedTransactionFactory

生成一个SpringManagedTransaction事务对象,封装在一个Executor(SimpleExecutor/ReuseExecutor/BatchExecutor)中,封装在DefaultSqlSession中并返回。

封装在SqlSessionHolder中,并以键值对绑定在当前线程<DefaultSqlSessionFactory,SqlSessionHolder>

SqlSessionUtils 返回DefaultSqlSession

7. 调用DefaultSqlSession的(update/select等),其中

MappedStatement e = this.configuration.getMappedStatement(接口名.方法名 statement);

this.executor.query/update

8. 回到第6步生成的Executor,doupdate/doquery时会prepareStatement,其中会getConnection调用SpringManagedTransaction事务对象的getConnection(),

DataSourceUtils.getConnection(this.dataSource);

看 mybatis--MapperProxy事务 最后分析的

ConnectionHolder conHolder = (ConnectionHolder)TransactionSynchronizationManager.getResource(dataSource);

使用的是第三步当前线程的键值对,也就是service层开启spring事务的connection

其实,神秘的spring事务本质还是jdbc的connection,跟我们直接使用jdbc是一样的,但是做了增强

原文地址:https://www.cnblogs.com/yhzh/p/5589327.html