1. 程式人生 > >mybatis原始碼解析(五)-mybatis如何實現的事務控制

mybatis原始碼解析(五)-mybatis如何實現的事務控制

這篇部落格主要展示mybatis是如何控制事務的。

下面兩個例子分別展示一下我們使用/不使用Trancation的例子。

Code 1不使用事務,自動提交

    SqlSession session = sqlSessionFactory.openSession(true);
    session.insert("insert into table1(id, name) values(1, 'a');");
    session.insert("insert into table1(id, name) values(2, 'b');");

Code 2使用事務,不自動提交

    SqlSession session = sqlSessionFactory.openSession(false);
    try {
        session.insert
("insert into table1(id, name) values(1, 'a');");
session.insert("insert into table1(id, name) values(2, 'b');"); session.commit(); } catch (Exception e) { session.rollback(); }

在mybatis api中,控制Trancation是在建立org.apache.ibatis.session.SqlSession的時候設定boolean型別的引數來實現的。呼叫方法沒有差別,支援事務的最後會呼叫commoit或者rollback。

建立SqlSession

建立org.apache.ibatis.session.SqlSession的過程如下:

Code 3
org.apache.ibatis.session.defaults.DefaultSqlSessionFactory

    private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
        Transaction tx = null;
        DefaultSqlSession var8;
        try
{ Environment environment = this.configuration.getEnvironment(); TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment); tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit); Executor executor = this.configuration.newExecutor(tx, execType); var8 = new DefaultSqlSession(this.configuration, executor, autoCommit); } catch (Exception var12) { this.closeTransaction(tx); throw ExceptionFactory.wrapException("Error opening session. Cause: " + var12, var12); } finally { ErrorContext.instance().reset(); } return var8; }

第7行建立了Transaction物件。第8行建立了Executor物件。第9行建立了SqlSession物件。下面第這三個物件做一個簡單介紹:

  • 1、org.apache.ibatis.session.SqlSession

使用者直接操作的物件,該物件對使用者呼叫的方法進行一些簡單的處理,然後呼叫Executor的方法執行具體的操作。
可以注意一下,該物件維護了一個private boolean dirty;用來標記在上次commit之後有沒有執行新的增、刪、改操作。該類的commit會根據這個屬性來確定會不會執行jdbc程式碼的commit方法,也可以強制commit而跳過這個屬性的限制。

  • 2、org.apache.ibatis.executor.Executor

該物件是具體執行sql的類,它操作的是org.apache.ibatis.mapping.MappedStatement,這個物件在執行真正的sql時,會使用jdbc的java.sql.Connection,但是它不會去生成、維護這個java.sql.Connection,它包含了一個org.apache.ibatis.transaction.Transaction,由Transaction這個物件去維護Transaction

  • 3、org.apache.ibatis.transaction.Transaction

這是個介面,介面的定義如下:

Code 4
org.apache.ibatis.transaction.Transaction

    public interface Transaction {
        Connection getConnection() throws SQLException;
        void commit() throws SQLException;
        void rollback() throws SQLException;
        void close() throws SQLException;
    }

它的一個實現類org.apache.ibatis.transaction.jdbc.JdbcTransaction,這個類裡維護了DataSource,在需要的時候會建立java.sql.Connection,在建立完java.sql.Connection後,會根據建立org.apache.ibatis.session.SqlSession時傳遞的引數值,設定java.sql.Connection是否自動提交。該類也提供了對Connection執行commit、rollback的方法,在org.apache.ibatis.session.SqlSession執行commit、rollback方法時,都會傳遞到這裡的方法。

總結

我們使用Jdbc進行事務控制的話,也是呼叫java.sql.Connection.setAutoCommit設定是否開啟事務,呼叫java.sql.Connection.commitjava.sql.Connection.rollback進行調或回滾。在mybatis程式碼中,通過org.apache.ibatis.session.SqlSession的建立設定是否支援事務,呼叫org.apache.ibatis.session.SqlSession.commitorg.apache.ibatis.session.SqlSession.rollback方法會對映到對應Jdbc的方法,這樣就足以支援了事務。