MyBatisトランザクション---JdbcTransaction

11469 ワード

Mybatisがトランザクションを管理するには、次の2つの方法があります.
(1)  JDBC       ,    java.sql.Connection           
(2)  MANAGED       ,    mybatis           ,        (JBOSS,WebLogic)         

JdbcTransaction
本文は主に第一の方式を学ぶ.
まずJDBCのトランザクションの復習:データベース接続の取得:connctionオブジェクト開始トランザクション:connction.settAutoCommit(false)、falseはトランザクションを自動的にコミットしないことを示します.トランザクションのコミット:connction.commit();トランザクションロールバック:connction.rollback();
たとえば、次のコードで削除操作を行います.
        //        
        String resource = "sqlMapConfig.xml";
        InputStream in = Resources.getResourceAsStream(resource);
        //  SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        //  SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //  Mapper
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        userMapper.deleteUserById(31);
        //     ,       ,          
        sqlSession.commit();
        //    
        sqlSession.close();

mybatisは自動的にトランザクションを開始し、トランザクションを自動的にコミットしないように設定します.
しかし、事務はいつ開かれたのか、ソースコードをすり抜けた.トランザクションは1回のSqlSessionセッションに含まれるため、セッションの作成から分析を開始します.つまり、SqlSessionFactoryのopenSessionメソッドから分析を開始します.
SqlSessionFactoryは、2つの実装クラス、DefaultSqlSessionFactoryとSqlSessionManagerを持つインタフェースで、デフォルトではDefaultSqlSessionFactoryが使用されます. 
DefaultSqlSessionFactoryのopenSession()メソッド:
public SqlSession openSession() {
        return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), (TransactionIsolationLevel)null, false);
    }

呼び出しました:openSessionFromDataSourceメソッド:
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);
            //         ,   executor,     SqlSession         ,       executor  。
            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;
    }

ここにはトランザクションファクトリTransactionFactoryがインスタンス化されています.TransactionFactoryはインタフェースです.
JdbcTransactionFactoryとM a g edTransactionFactoryの2つの実装クラスもあります.JDBCトランザクションを使用しているので、JdbcTransactionFactoryのnewTransactionメソッドを使用してJdbcTransactionを作成します.
JdbcTransactionソースの表示:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.apache.ibatis.transaction.jdbc;

import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.session.TransactionIsolationLevel;
import org.apache.ibatis.transaction.Transaction;
import org.apache.ibatis.transaction.TransactionException;

public class JdbcTransaction implements Transaction {
    private static final Log log = LogFactory.getLog(JdbcTransaction.class);
    protected Connection connection;
    protected DataSource dataSource;
    protected TransactionIsolationLevel level;
    protected boolean autoCommmit;

    public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) {
        this.dataSource = ds;
        this.level = desiredLevel;
        this.autoCommmit = desiredAutoCommit;
    }

    public JdbcTransaction(Connection connection) {
        this.connection = connection;
    }

    //       
    public Connection getConnection() throws SQLException {
        if (this.connection == null) {
            this.openConnection();
        }

        return this.connection;
    }

    //    
    public void commit() throws SQLException {
        if (this.connection != null && !this.connection.getAutoCommit()) {
            if (log.isDebugEnabled()) {
                log.debug("Committing JDBC Connection [" + this.connection + "]");
            }

            this.connection.commit();
        }

    }

    //    
    public void rollback() throws SQLException {
        if (this.connection != null && !this.connection.getAutoCommit()) {
            if (log.isDebugEnabled()) {
                log.debug("Rolling back JDBC Connection [" + this.connection + "]");
            }

            this.connection.rollback();
        }

    }

    //    
    public void close() throws SQLException {
        if (this.connection != null) {
            this.resetAutoCommit();
            if (log.isDebugEnabled()) {
                log.debug("Closing JDBC Connection [" + this.connection + "]");
            }

            this.connection.close();
        }

    }

    //          
    protected void setDesiredAutoCommit(boolean desiredAutoCommit) {
        try {
            if (this.connection.getAutoCommit() != desiredAutoCommit) {
                if (log.isDebugEnabled()) {
                    log.debug("Setting autocommit to " + desiredAutoCommit + " on JDBC Connection [" + this.connection + "]");
                }

                this.connection.setAutoCommit(desiredAutoCommit);
            }

        } catch (SQLException var3) {
            throw new TransactionException("Error configuring AutoCommit.  Your driver may not support getAutoCommit() or setAutoCommit(). Requested setting: " + desiredAutoCommit + ".  Cause: " + var3, var3);
        }
    }

    //        
    protected void resetAutoCommit() {
        try {
            if (!this.connection.getAutoCommit()) {
                if (log.isDebugEnabled()) {
                    log.debug("Resetting autocommit to true on JDBC Connection [" + this.connection + "]");
                }

                this.connection.setAutoCommit(true);
            }
        } catch (SQLException var2) {
            log.debug("Error resetting autocommit to true before closing the connection.  Cause: " + var2);
        }

    }

    protected void openConnection() throws SQLException {
        if (log.isDebugEnabled()) {
            log.debug("Opening JDBC Connection");
        }

        this.connection = this.dataSource.getConnection();
        if (this.level != null) {
            this.connection.setTransactionIsolation(this.level.getLevel());
        }

        this.setDesiredAutoCommit(this.autoCommmit);
    }
}

getConnection()メソッドでopenConnection()メソッドを呼び出し、データベース接続を取得し、レベルを設定し、トランザクションを開始します.
上のopenSessionFromDataSourceメソッドに戻り、トランザクション・オブジェクトを作成した後、次に2つのオブジェクトをインスタンス化しました.1つはExecutorオブジェクト、1つのDefaultSqlSessionオブジェクトであり、このオブジェクトを返し、getConnection()メソッドを呼び出していないので、トランザクションの開始はOpenSessionメソッドではありません.では、トランザクションの開始を推測します.データベースにSql文を送信する準備をしている間に、一番上の削除を実行するコードに戻ります.
//        
        String resource = "sqlMapConfig.xml";
        InputStream in = Resources.getResourceAsStream(resource);
        //  SqlSessionFactory
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        //  SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //  Mapper
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        userMapper.deleteUserById(31);
        //     ,       ,          
        sqlSession.commit();
        //    
        sqlSession.close();

ここにいるよdeleteUserById(31)ここでブレークポイントを打った後、SimpleExecutor発doUpdateメソッドを追跡しました.SimpleExecutorはExecutorの実装クラスです.
public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
        Statement stmt = null;

        int var6;
        try {
            Configuration configuration = ms.getConfiguration();
            StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, (ResultHandler)null, (BoundSql)null);
            stmt = this.prepareStatement(handler, ms.getStatementLog());
            var6 = handler.update(stmt);
        } finally {
            this.closeStatement(stmt);
        }

        return var6;
    }

次に、prepareStatement()メソッドを表示します.
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
        Connection connection = this.getConnection(statementLog);
        Statement stmt = handler.prepare(connection);
        handler.parameterize(stmt);
        return stmt;
    }

getConnectionが見えて、追いかけ続けます:
BaseExecutorのgetConnectionメソッドにアクセスするには、次の手順に従います.
 protected Connection getConnection(Log statementLog) throws SQLException {
        Connection connection = this.transaction.getConnection();
        return statementLog.isDebugEnabled() ? ConnectionLogger.newInstance(connection, statementLog, this.queryStack) : connection;
    }

Connection connection = this.transaction.getConnection();この文は転送されたtransactionのgetConnectionメソッドを呼び出し、ここでのtransactionはopensessionメソッドでインスタンス化し、転送します.これでやっと事務がどこで開かれたのかを見つけた.
たくさん分析しました:実は覚えている限り、MyBatisがJDBCを使ってトランザクション管理を行う場合、デフォルトでトランザクションが開始され、自動的にトランザクションがコミットされないように設定されています.
package com.xf.app1;

import com.xf.app1.mapper.UserMapper;
import com.xf.app1.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class Xml_SqlSessionFactory {

    public static void main(String[] args) {
        SqlSessionFactory sqlSessionFactory;
        SqlSession sqlSession = null;
        //        mybatis     (           )
        try {
            //mybatis    
            String resource = "com/xf/app1/mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            //          sql sqlSession
             sqlSession = sqlSessionFactory.openSession();

             //  mapper  
            UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
            User user1 =userMapper.selectUser(1L) ;
            System.out.println(user1);

            userMapper.deleteUserById(1L);//              

            //      
            User user = sqlSession.selectOne("com.xf.app1.mapper.UserMapper.selectUser", 1);
            System.out.println(user);

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (sqlSession != null) {
                sqlSession.close();
            }
        }

    }

}