美文网首页mybatis
Mybatis Executor模块分析

Mybatis Executor模块分析

作者: 晴天哥_王志 | 来源:发表于2022-01-02 23:24 被阅读0次

系列

开篇

 梳理mybatis核心关键流程,打通datasource在mybatis的流程中的作用点。

  • MapperMethod解析参数,参考mybatis 参数解析流程附相关案例
  • DefaultSqlSessionFactory#openSessionFromDataSource负责创建SqlSession对象。
  • Executor负责创建StatementHandler和通过prepareStatement初始化Statement对象。
  • SqlSession作为入口,内部通过Executor执行真正的SQL操作。

DefaultSqlSessionFactory

public class DefaultSqlSessionFactory implements SqlSessionFactory {

  private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
      final Environment environment = configuration.getEnvironment();
      // 创建事务对象工厂SpringManagedTransactionFactory
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      // 创建事务对象SpringManagedTransaction
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
      // 创建Executor对象
      final Executor executor = configuration.newExecutor(tx, execType);
      // 创建SqlSession对象
      return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
    } finally {
    }
  }
}
  • 通过openSessionFromDataSource返回SqlSession对象。
  • SqlSession包含Executor,Executor包含tx,tx包含DataSource。
  • mybatis的执行逻辑通过SqlSession调用Executor来进行执行。

Executor

public class Configuration {

  public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
    executorType = executorType == null ? defaultExecutorType : executorType;
    executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
    Executor executor;
    if (ExecutorType.BATCH == executorType) {
      executor = new BatchExecutor(this, transaction);
    } else if (ExecutorType.REUSE == executorType) {
      executor = new ReuseExecutor(this, transaction);
    } else {
      executor = new SimpleExecutor(this, transaction);
    }
    if (cacheEnabled) {
      executor = new CachingExecutor(executor);
    }
    executor = (Executor) interceptorChain.pluginAll(executor);
    return executor;
  }
}
  • Configuration#newExecutor负责创建Executor对象。

DefaultSqlSession

public class DefaultSqlSession implements SqlSession {

  private Configuration configuration;
  private Executor executor;
  private boolean autoCommit;
  private boolean dirty;

  public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
    this.configuration = configuration;
    this.executor = executor;
    this.dirty = false;
    this.autoCommit = autoCommit;
  }

  public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
    try {
      MappedStatement ms = configuration.getMappedStatement(statement);
      return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
    } catch (Exception e) {
    } finally {
    }
  }
}
  • DefaultSqlSession包含Executor对象,核心组件参考mybatis组件关系图
  • SqlSession的执行逻辑通过executor来执行,针对列表参数通过wrapCollection进行包装。

SimpleExecutor

public class SimpleExecutor extends BaseExecutor {

  @Override
  public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
    Statement stmt = null;
    try {
      Configuration configuration = ms.getConfiguration();
      // 创建StatementHandler对象
      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
      // 初始化Statement
      stmt = prepareStatement(handler, ms.getStatementLog());
      // 通过StatementHandler对象进行查询
      return handler.<E>query(stmt, resultHandler);
    } finally {
      closeStatement(stmt);
    }
  }
}
  • 创建StatementHandler对象,包括boundSql、parameterHandler、resultSetHandler。
  • 执行Statement的初始化操作,执行从Datasource到Connection到Statement的初始化。
  • 通过StatementHandler执行SQL操作。

StatementHandler

public class Configuration {

  public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
    StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
    statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
    return statementHandler;
  }
}

public class RoutingStatementHandler implements StatementHandler {

  public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {

    switch (ms.getStatementType()) {
      case STATEMENT:
        delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        break;
      case PREPARED:
        delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        break;
      case CALLABLE:
        delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        break;
      default:
        throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
    }
}


public class PreparedStatementHandler extends BaseStatementHandler {

  public PreparedStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
    super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
  }
}

public abstract class BaseStatementHandler implements StatementHandler {

  protected final Configuration configuration;
  protected final ObjectFactory objectFactory;
  protected final TypeHandlerRegistry typeHandlerRegistry;
  protected final ResultSetHandler resultSetHandler;
  protected final ParameterHandler parameterHandler;
  protected final Executor executor;
  protected final MappedStatement mappedStatement;
  protected final RowBounds rowBounds;
  protected BoundSql boundSql;

  protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
    this.configuration = mappedStatement.getConfiguration();
    this.executor = executor;
    this.mappedStatement = mappedStatement;
    this.rowBounds = rowBounds;

    this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
    this.objectFactory = configuration.getObjectFactory();

    if (boundSql == null) { // issue #435, get the key before calculating the statement
      generateKeys(parameterObject);
      boundSql = mappedStatement.getBoundSql(parameterObject);
    }

    this.boundSql = boundSql;

    this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
    this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
  }
}
  • StatementHandler的创建过程中负责生成boundSql、parameterHandler、resultSetHandler。

Statement

public class SimpleExecutor extends BaseExecutor {

  private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
    Statement stmt;
    // 1、获取连接
    Connection connection = getConnection(statementLog);
    // 2、获取会话Statement对象
    stmt = handler.prepare(connection);
    // 3、初始化参数格式
    handler.parameterize(stmt);

    return stmt;
  }
}


public abstract class BaseExecutor implements Executor {

  protected Connection getConnection(Log statementLog) throws SQLException {
    // 1、从SpringManagedTransaction获取连接
    Connection connection = transaction.getConnection();
    if (statementLog.isDebugEnabled()) {
      return ConnectionLogger.newInstance(connection, statementLog, queryStack);
    } else {
      return connection;
    }
  }
}

public class SpringManagedTransaction implements Transaction {

  private final DataSource dataSource;
  private Connection connection;
  private boolean isConnectionTransactional;
  private boolean autoCommit;

  public SpringManagedTransaction(DataSource dataSource) {
    this.dataSource = dataSource;
  }

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

  private void openConnection() throws SQLException {
    this.connection = DataSourceUtils.getConnection(this.dataSource);
    this.autoCommit = this.connection.getAutoCommit();
    this.isConnectionTransactional = DataSourceUtils.isConnectionTransactional(this.connection, this.dataSource);
  }
}

<br>
##PreparedStatementHandler
public abstract class DataSourceUtils {

    public static Connection getConnection(DataSource dataSource) throws CannotGetJdbcConnectionException {
        try {
            return doGetConnection(dataSource);
        }
        catch (SQLException ex) {
        }
    }

    public static Connection doGetConnection(DataSource dataSource) throws SQLException {

        ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
        if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) {
            conHolder.requested();
            if (!conHolder.hasConnection()) {
                conHolder.setConnection(dataSource.getConnection());
            }
            return conHolder.getConnection();
        }
        // 从dataSource获取链接
        Connection con = dataSource.getConnection();

        if (TransactionSynchronizationManager.isSynchronizationActive()) {
            try {
                ConnectionHolder holderToUse = conHolder;
                if (holderToUse == null) {
                    holderToUse = new ConnectionHolder(con);
                }
                else {
                    holderToUse.setConnection(con);
                }
                holderToUse.requested();
                TransactionSynchronizationManager.registerSynchronization(
                        new ConnectionSynchronization(holderToUse, dataSource));
                holderToUse.setSynchronizedWithTransaction(true);
                if (holderToUse != conHolder) {
                    TransactionSynchronizationManager.bindResource(dataSource, holderToUse);
                }
            }
            catch (RuntimeException ex) {
                releaseConnection(con, dataSource);
                throw ex;
            }
        }

        return con;
    }
}
  • DataSourceUtils#doGetConnection从Datasource获取Connection对象。

PreparedStatementHandler

public abstract class BaseStatementHandler implements StatementHandler {

  @Override
  public Statement prepare(Connection connection) throws SQLException {
    ErrorContext.instance().sql(boundSql.getSql());
    Statement statement = null;
    try {
      statement = instantiateStatement(connection);
      setStatementTimeout(statement);
      setFetchSize(statement);
      return statement;
    } catch (SQLException e) {
    } catch (Exception e) {
    }
  }
}

public class PreparedStatementHandler extends BaseStatementHandler {

  @Override
  protected Statement instantiateStatement(Connection connection) throws SQLException {
    String sql = boundSql.getSql();
    if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {
      String[] keyColumnNames = mappedStatement.getKeyColumns();
      if (keyColumnNames == null) {
        return connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
      } else {
        return connection.prepareStatement(sql, keyColumnNames);
      }
    } else if (mappedStatement.getResultSetType() != null) {
      return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
    } else {
      // 执行connection的prepareStatement操作
      return connection.prepareStatement(sql);
    }
  }
}
  • instantiateStatement执行connection的prepareStatement操作。

结论

  • 分库分布核心思想在于自定义Datasource并且重新getConnection返回动态代理的Connection对象。
  • Connection对象使用动态代理生成的对象在于可以自定义其他的操作。
  • 定义以StatementHandler的prepare方法作为切入点的插件,因为Mysql查询过程中的statement是在StatementHandler#prepare中生成。

相关文章

网友评论

    本文标题:Mybatis Executor模块分析

    本文链接:https://www.haomeiwen.com/subject/kcrzqrtx.html