MyBatisセッション生成の内部メカニズム

データベース操作のたびに新しいセッションを生成する必要があり、openSession()メソッドを使用して作成します。

SqlSession session = sqlSessionFactory.openSession();

このsqlSessionFactoryはデフォルトの実装クラスを使用しており、openSessionFromDataSource()メソッド内で生成されます。

private SqlSession openSessionFromDataSource(ExecutorType execType, 
                                           TransactionIsolationLevel level, 
                                           boolean autoCommit) {
    Transaction transaction = null;
    try {
        final Environment env = configuration.getEnvironment();
        // トランザクションファクトリの取得
        final TransactionFactory txFactory = getTransactionFactoryFromEnvironment(env);
        // トランザクションの生成
        transaction = txFactory.newTransaction(env.getDataSource(), level, autoCommit);
        // トランザクションファクトリと実行タイプに基づくエグゼキュータの生成
        final Executor sqlExecutor = configuration.newExecutor(transaction, execType);
        return new DefaultSqlSession(configuration, sqlExecutor, autoCommit);
    } catch (Exception ex) {
        closeTransaction(transaction);
        throw ExceptionFactory.wrapException("セッションオープンエラー: " + ex, ex);
    } finally {
        ErrorContext.instance().reset();
    }
}

この処理にはSQLを実行するためのExecutorが含まれています。Executorにはトランザクションタイプと実行タイプの指定が必要です。

まずConfigurationからEnvironmentを取得し、environmentにはトランザクションファクトリが含まれています。

  1. トランザクションの生成

EnvironmentオブジェクトからTransactionFactoryを取得します。これは<environments>タグの解析時に生成されます。

final Environment env = configuration.getEnvironment();
// トランザクションファクトリの取得
final TransactionFactory txFactory = getTransactionFactoryFromEnvironment(env);
// トランザクションの生成
transaction = txFactory.newTransaction(env.getDataSource(), level, autoCommit);

トランザクションファクトリはJDBCまたはMANAGEDに設定可能です。

属性 ファクトリクラス トランザクション

JDBC JdbcTransactionFactory JdbcTransaction

MANAGED ManagedTransactionFactory ManagedTransaction

  • JDBC Connectionオブジェクトのcommit()、rollback()、close()メソッドを使用してトランザクションを管理します。
  • MANAGED トランザクションをコンテナ(JBOSS、Weblogicなど)に委譲します。ローカルプログラムでは呼び出されず、トランザクションは発生しません。

Spring+MyBatisの組み合わせでは設定は不要です。applicationContext.xmlでデータソースとトランザクションマネージャを直接設定し、MyBatisの設定を上書きします。

  1. Executorの生成

newExecutorメソッドを使用して生成します:

final Executor sqlExecutor = configuration.newExecutor(transaction, execType);
  • エグゼキュータの生成 Executorの基本タイプは3種類:SIMPLE、REUSE、BATCH、デフォルトはSIMPLE(settingsElement()でデフォルト値を読み込み)。
if (ExecutorType.BATCH == executorType) {
    executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
    executor = new ReuseExecutor(this, transaction);
} else {
    // デフォルトはSimpleExecutor
    executor = new SimpleExecutor(this, transaction);
}

これらはすべて抽象クラスBaseExecutorを継承しています。抽象クラスはExecutorインターフェースを実装しています。

この呼び出しは、抽象クラスBaseExecutorがExecutorインターフェースを実装し、具象クラスが抽象クラスの実装を継承するというテンプレートメソッドパターンの実装です。

テンプレートメソッドはアルゴリズムの骨格を定義し、サブクラスが1つ以上のステップの実装を提供できるようにします。テンプレートメソッドにより、サブクラスはアルゴリズム構造を変更せずに特定のステップを再定義できます。

抽象メソッドはサブクラスで実装され、BaseExecutorは最終的に具体的なサブクラスを呼び出します。

protected abstract int doUpdate(MappedStatement ms, Object parameter)
    throws SQLException;

protected abstract List<BatchResult> doFlushStatements(boolean isRollback)
    throws SQLException;

protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, 
                                     RowBounds rowBounds, 
                                     ResultHandler resultHandler, 
                                     BoundSql boundSql)
    throws SQLException;
  • キャッシュデコレーション cacheEnabled=trueの場合、デコレータパターンを使用してexecutorを装飾します。
// セカンダリキャッシュ設定、settingsのcacheEnabledはデフォルトtrue
if (cacheEnabled) {
    executor = new CachingExecutor(executor);
}
  • プラグインプロキシ 装飾完了後、以下の処理を実行:
// プラグインロジックの適用、これで4大オブジェクトすべてにインターセプトが適用済み
executor = (Executor) interceptorChain.pluginAll(executor);
  • SqlSession実装クラスの返却 最終的にDefaultSqlSessionを返却し、その属性にはConfigurationとExecutorオブジェクトが含まれます。
return new DefaultSqlSession(configuration, executor, autoCommit);

まとめ

セッション生成プロセスを通じて、DefaultSqlSessionを取得します。これにはExecutorが含まれており、ExecutorはSQLの実際の実行オブジェクトです。

セッション生成フロー

タグ: MyBatis SqlSession Executor Transaction DataSource

5月16日 03:09 投稿