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.commit或java.sql.Connection.rollback進行調或回滾。在mybatis程式碼中,通過org.apache.ibatis.session.SqlSession的建立設定是否支援事務,呼叫org.apache.ibatis.session.SqlSession.commit、org.apache.ibatis.session.SqlSession.rollback方法會對映到對應Jdbc的方法,這樣就足以支援了事務。