spring--mybatis事務總結

spring--事務原理mybatis--MapperScannerConfigurer 和 mybatis--MapperProxy事務,最近想把spring mybatis中的事務和mapper接口的原理分析分析,陸陸續續寫了些,這篇作個總結。html

spring+mybatis mapper接口 聲明式事務配置java

<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,其它的是supportsweb

1. org.mybatis.spring.SqlSessionFactoryBean解析mapper xml配置,根據namespace添加class mapper組裝Configuration對象,設置它的environment(包含springManagedTransactionFactory),最後getObject()包裝出DefaultSqlSessionFactory;spring

 

2. org.mybatis.spring.mapper.MapperScannerConfigurer掃描basePackage下的mapper接口,每一個接口封裝爲MapperFactoryBean(包含封裝了DefaultSqlSessionFactory的SqlSessionTemplate),註冊給spring容器。sql

ps:當調用"mapper接口"時去DefaultSqlSessionFactory-》Configuration得到接口類的代理類express

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

 

3. 前面兩步是系統的前提工做。mybatis

從service層方法開始,首先進入TransactionInerceptor事務攔截器,由 DataSourceTransactionManager 生成一個DataSourceTransactionObject事務對象,封裝在DefaultTransactionStatus中,調用doBegin開啓這個事務對象,設置這個事務對象 setConnectionHolder(new ConnectionHolder(Connection ex)),把這個ConnectionHolder 以鍵值對綁定在當前線程上 <this.getDataSource(),txObject.getConnectionHolder()>app

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

返回這個 DefaultTransactionStatus對象,封裝在TransactionAspectSupport.TransactionInfo中,綁定在當前線程上,以後調用實際service方法ui

 

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是同樣的,可是作了加強

相關文章
相關標籤/搜索