1. 程式人生 > >MyBatis原始碼閱讀——MyBatis對事務的處理過程分析

MyBatis原始碼閱讀——MyBatis對事務的處理過程分析

事務管理器

在 MyBatis 中有兩種型別的事務管理器(也就是 type=”[JDBC|MANAGED]”):

 <environments default="development">
        <environment id="development">
            <!-- 配置事務管理器 -->
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1/learn?useUnicode=true&amp;characterEncoding=utf-8"/>
                <property name="username" value="root"/>
                <property name="password" value="12345"/>
            </dataSource>
        </environment>
    </environments>

* JDBC – 這個配置就是直接使用了 JDBC 的提交和回滾設定,它依賴於從資料來源得到的連線來管理事務作用域。即利用java.sql.Connection物件完成對事務的提交(commit())、回滾(rollback())、關閉(close())等
* MANAGED – 這個配置幾乎沒做什麼。它從來不提交或回滾一個連線,而是讓容器來管理事務的整個生命週期(比如 JEE 應用伺服器的上下文)。 預設情況下它會關閉連線,然而一些容器並不希望這樣,因此需要將 closeConnection 屬性設定為 false 來阻止它預設的關閉行為。這種機制MyBatis自身不會去實現事務管理,而是讓程式的容器如(JBOSS,Weblogic)來實現對事務的管理。

    < transactionManager type="MANAGED">
        < property name="closeConnection" value="false"/>
    </ transactionManager>

如果你正在使用 Spring + MyBatis,則沒有必要配置事務管理器, 因為 Spring 模組會使用自帶的管理器來覆蓋前面的配置。

這裡寫圖片描述
這兩種事務管理器型別都不需要任何屬性。它們不過是類型別名,換句話說,你可以使用 TransactionFactory 介面的實現類的完全限定名或類型別名代替它們。

事務使用

JdbcTransaction

JdbcTransaction由TransactionFactory->openSessionFromConnection()方法生成
這裡寫圖片描述
這裡寫圖片描述
從JdbcTransaction的原始碼中,你應該可以看出,JdbcTransaction主要是對java.sql.Connection事務處理中的事務進行了一層封裝。

ManagedTransaction

這裡寫圖片描述
在ManagedTransaction原始碼中,commit,rollback方法全是空的,它讓容器管理事務transaction的整個生命週期。也就是說,ManagedTransaction不會幫我們commit和rollback。
執行一段程式碼看下效果:

String resource = "mybatis/conf/mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //從 XML 中構建 SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession session = sqlSessionFactory.openSession(false);

        Blog blog = new Blog();
        blog.setBlogTitle("這是標題1");
        blog.setBlogContent("這是內容2");
        blog.setCreateTime(new Date());

        try {
            BlogMapper mapper = session.getMapper(BlogMapper.class);
            mapper.insert(blog);
            session.commit();
        }catch (Exception e){
            //手動回滾
            session.rollback();
        }finally {
            session.close();
        }

在我們未開啟自動提交的情況下(事務必須關閉)它都是執行的空操作。不會影響資料庫。

SpringManagedTransaction

在mybatis-spring jar包中,在SqlSession執行sql時通過用SpringManagedTransaction代替mybatis的JdbcTransaction,讓SqlSession從spring的ThreadLocal中獲取jdbc connection。關於Spring的事務處理原理可以看下此篇部落格:https://blog.csdn.net/qq_18860653/article/details/80049281

參考文件