mybatis原理初探()

Mybatis执行原理初探

初始化

  • 加载配置文件
    String resource = “mybatis.xml”;

    // 加载mybatis的配置文件(它也加载关联的映射文件)
    InputStream inputStream = null;
    try {
    inputStream = Resources.getResourceAsStream(resource);
    } catch (IOException e) {
    e.printStackTrace();
    }

  • 构建sqlsession工厂
    // 构建sqlSession的工厂
    sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

  • SqlSessionFactoryBuilder类中build方法
    // SqlSessionFactoryBuilder类
    public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
    XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
    return build(parser.parse()); // 开始进行解析了 🙂
    } catch (Exception e) {
    throw ExceptionFactory.wrapException(“Error building SqlSession.”, e);
    } finally {
    ErrorContext.instance().reset();
    try {
    inputStream.close();
    } catch (IOException e) {
    // Intentionally ignore. Prefer previous error.
    }
    }
    }

  • XMLConfigBuilder类的parse方法解析配置文件和mapper文件,生成configuration
    // XMLConfigBuilder类
    public Configuration parse() {
    if (parsed) {
    throw new BuilderException(“Each XMLConfigBuilder can only be used once.”);
    }
    parsed = true;
    parseConfiguration(parser.evalNode(“/configuration”));
    return configuration;
    }

    private void parseConfiguration(XNode root) {
    try {
    //issue #117 read properties first
    propertiesElement(root.evalNode(“properties”));
    Properties settings = settingsAsProperties(root.evalNode(“settings”));
    loadCustomVfs(settings);
    typeAliasesElement(root.evalNode(“typeAliases”));
    pluginElement(root.evalNode(“plugins”));
    objectFactoryElement(root.evalNode(“objectFactory”));
    objectWrapperFactoryElement(root.evalNode(“objectWrapperFactory”));
    reflectorFactoryElement(root.evalNode(“reflectorFactory”));
    settingsElement(settings);
    // read it after objectFactory and objectWrapperFactory issue #631

    /* 处理environments节点数据 */
    environmentsElement(root.evalNode(“environments”));
    databaseIdProviderElement(root.evalNode(“databaseIdProvider”));
    typeHandlerElement(root.evalNode(“typeHandlers”));
    mapperElement(root.evalNode(“mappers”));
    } catch (Exception e) {
    throw new BuilderException(“Error parsing SQL Mapper Configuration. Cause: ” + e, e);
    }
    }

  • SqlSessionFactoryBuilder类的build(configuration)方法得到XMLConfigBuilder的parse()方法的返回值configuration生成DefaultSqlSessionFactory,初始化完成
    // SqlSessionFactoryBuilder类
    public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
    }

SqlSession

四个重要的对象

1.Executor执行器

调度执行StatmentHandler、ParameterHandler、ResultHandler执行相应的SQL语句
  • Executor执行器有三种:简易执行器SIMPLE(不配置就是默认执行器)、REUSE是一种重用预处理语句、BATCH批量更新、批量专用处理器
  • 执行器的作用:Executor会先调用StatementHandler的prepare()方法预编译SQL语句,同时设置一些基本的运行参数,然后调用StatementHandler的parameterize()方法(实际上是启用了ParameterHandler设置参数)设置参数,resultHandler再组装查询结果返回调用者完成一次查询完成预编译,简单总结起来就是即先预编译SQL语句,之后设置参数(跟JDBC的prepareStatement过程类似)最后如果有查询结果就会组装返回
  • Executor源码:

    executor的来历:Configuration类的newExecutor()方法(下文举例返回SimpleExecutor对象)
    //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;
    }

    SimpleExecutor继承了BaseExecuror抽象类,BaseExecurot实现了Executor接口,simpleExecutor只有一个prepareStatement方法,其他方法均来自抽象类BaseExecutor
    public class SimpleExecutor extends BaseExecutor
    public abstract class BaseExecutor implements Executor

    调用prepareStatement()方法,在其中调用StatementHandler的prepare()和parameterize()方法
    //SimpleExecutor类
    private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
    Statement stmt;
    Connection connection = getConnection(statementLog);
    stmt = handler.prepare(connection, transaction.getTimeout());
    handler.parameterize(stmt);
    return stmt;
    }

  • executor的来历:Configuration类的newExecutor()方法(下文举例返回SimpleExecutor对象)
    //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;
    }

  • SimpleExecutor继承了BaseExecuror抽象类,BaseExecurot实现了Executor接口,simpleExecutor只有一个prepareStatement方法,其他方法均来自抽象类BaseExecutor
    public class SimpleExecutor extends BaseExecutor
    public abstract class BaseExecutor implements Executor
  • 调用prepareStatement()方法,在其中调用StatementHandler的prepare()和parameterize()方法
    //SimpleExecutor类
    private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
    Statement stmt;
    Connection connection = getConnection(statementLog);
    stmt = handler.prepare(connection, transaction.getTimeout());
    handler.parameterize(stmt);
    return stmt;
    }

2.StatamentHandler数据库会话器

使用数据库中Statement(PrepareStatement)执行操作,即底层是封装好了的prepareStatement
  • 作用:
    简单来说就是专门处理数据库会话。详细来说就是进行预编译并且调用ParameterHandler的setParameters()方法设置参数
  • StatementHandler有三种:
    SimpleStatementHandler、PrepareStatementHandler、CallableStatementHandler,分别对应Executor的三种执行器(SIMPLE、REUSE、BATCH)
  • StatementHandler源码

    来源:Configuration类中的newStatementHandler()方法,返回的实际是实现了StatementHandler接口的RoutingStatementHandler类
    //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;
    }

    RoutingStatementHandler根据传入的Executor执行器类型返回不同类型的StatementHandler(下文以SimpleStatementHandler为例)
    //RoutingStatementHandler类
    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());
    }

    }

    SimpleStatementHandler类继承了抽象类BaseStatementHandler实现了StatementHandler接口
    public class SimpleStatementHandler extends BaseStatementHandler
    public abstract class BaseStatementHandler implements StatementHandler

    在BaseStatementHandler中重写prepare()方法,instantiateStatement()方法完成预编译,之后设置一些基础配置(获取最大行数,超时)
    @Override
    public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
    ErrorContext.instance().sql(boundSql.getSql());
    Statement statement = null;
    try {
    statement = instantiateStatement(connection);
    setStatementTimeout(statement, transactionTimeout);
    setFetchSize(statement);
    return statement;
    } catch (SQLException e) {
    closeStatement(statement);
    throw e;
    } catch (Exception e) {
    closeStatement(statement);
    throw new ExecutorException(“Error preparing statement. Cause: ” + e, e);
    }
    }

    *instantiateStatement*()预编译实际上也是使用了JDBC的prepareStatement()完成预编译
    @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 {
    return connection.prepareStatement(sql);
    }
    }

    parameterize()方法实际上调用了PreparedStatementHandler类的ParameterHandler的setParameters()方法
    @Override
    public void parameterize(Statement statement) throws SQLException {
    parameterHandler.setParameters((PreparedStatement) statement);
    }

  • 来源:Configuration类中的newStatementHandler()方法,返回的实际是实现了StatementHandler接口的RoutingStatementHandler类
    //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;
    }

    RoutingStatementHandler根据传入的Executor执行器类型返回不同类型的StatementHandler(下文以SimpleStatementHandler为例)
    //RoutingStatementHandler类
    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());
    }

    }

  • SimpleStatementHandler类继承了抽象类BaseStatementHandler实现了StatementHandler接口
    public class SimpleStatementHandler extends BaseStatementHandler
    public abstract class BaseStatementHandler implements StatementHandler
  • 在BaseStatementHandler中重写prepare()方法,instantiateStatement()方法完成预编译,之后设置一些基础配置(获取最大行数,超时)
    @Override
    public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
    ErrorContext.instance().sql(boundSql.getSql());
    Statement statement = null;
    try {
    statement = instantiateStatement(connection);
    setStatementTimeout(statement, transactionTimeout);
    setFetchSize(statement);
    return statement;
    } catch (SQLException e) {
    closeStatement(statement);
    throw e;
    } catch (Exception e) {
    closeStatement(statement);
    throw new ExecutorException(“Error preparing statement. Cause: ” + e, e);
    }
    }

  • *instantiateStatement*()预编译实际上也是使用了JDBC的prepareStatement()完成预编译
    @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 {
    return connection.prepareStatement(sql);
    }
    }

  • parameterize()方法实际上调用了PreparedStatementHandler类的ParameterHandler的setParameters()方法
    @Override
    public void parameterize(Statement statement) throws SQLException {
    parameterHandler.setParameters((PreparedStatement) statement);
    }

3.ParameterHandler

处理Sql参数
  • 作用:对预编译中参数进行设置,如果有配置typeHandler,自然会对注册的typeHandler对参数进行处理
  • 源码

    Mybatis提供了ParamterHandler的默认实现类DefalutParameterHandler
    public interface ParameterHandler {

    Object getParameterObject();

    void setParameters(PreparedStatement ps) throws SQLException;

    }

    public class DefaultParameterHandler implements ParameterHandler
    ParameterHandler接口中的getParameterObject()方法是返回参数对象,setParameters()是设置预编译参数
    @Override
    public Object getParameterObject() {
    return parameterObject;
    }

    从parameterObject中取到参数,然后使用typeHandler(注册在Configuration中)进行参数处理:
    @Override
    public void setParameters(PreparedStatement ps) {
    ErrorContext.instance().activity(“setting parameters”).object(mappedStatement.getParameterMap().getId());
    List parameterMappings = boundSql.getParameterMappings();
    if (parameterMappings != null) {
    for (int i = 0; i < parameterMappings.size(); i++) { ParameterMapping parameterMapping = parameterMappings.get(i); if (parameterMapping.getMode() != ParameterMode.OUT) { Object value; String propertyName = parameterMapping.getProperty(); if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params value = boundSql.getAdditionalParameter(propertyName); } else if (parameterObject == null) { value = null; } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) { value = parameterObject; } else { MetaObject metaObject = configuration.newMetaObject(parameterObject); value = metaObject.getValue(propertyName); } TypeHandler typeHandler = parameterMapping.getTypeHandler(); JdbcType jdbcType = parameterMapping.getJdbcType(); if (value == null && jdbcType == null) { jdbcType = configuration.getJdbcTypeForNull(); } try { typeHandler.setParameter(ps, i + 1, value, jdbcType); } catch (TypeException | SQLException e) { throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e); } } } } }

  • Mybatis提供了ParamterHandler的默认实现类DefalutParameterHandler
    public interface ParameterHandler {

    Object getParameterObject();

    void setParameters(PreparedStatement ps) throws SQLException;

    }

    public class DefaultParameterHandler implements ParameterHandler
    ParameterHandler接口中的getParameterObject()方法是返回参数对象,setParameters()是设置预编译参数
    @Override
    public Object getParameterObject() {
    return parameterObject;
    }

  • 从parameterObject中取到参数,然后使用typeHandler(注册在Configuration中)进行参数处理:
    @Override
    public void setParameters(PreparedStatement ps) {
    ErrorContext.instance().activity(“setting parameters”).object(mappedStatement.getParameterMap().getId());
    List parameterMappings = boundSql.getParameterMappings();
    if (parameterMappings != null) {
    for (int i = 0; i < parameterMappings.size(); i++) { ParameterMapping parameterMapping = parameterMappings.get(i); if (parameterMapping.getMode() != ParameterMode.OUT) { Object value; String propertyName = parameterMapping.getProperty(); if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params value = boundSql.getAdditionalParameter(propertyName); } else if (parameterObject == null) { value = null; } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) { value = parameterObject; } else { MetaObject metaObject = configuration.newMetaObject(parameterObject); value = metaObject.getValue(propertyName); } TypeHandler typeHandler = parameterMapping.getTypeHandler(); JdbcType jdbcType = parameterMapping.getJdbcType(); if (value == null && jdbcType == null) { jdbcType = configuration.getJdbcTypeForNull(); } try { typeHandler.setParameter(ps, i + 1, value, jdbcType); } catch (TypeException | SQLException e) { throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e); } } } } }

4.ResultSetHandler结果集处理器:

结果集ResultSet封装处理返回
  • 作用:组装结果返回结果集
  • 源码:

    ResultSetHandler接口,handlerResultSets()是包装并返回结果集的,handleOutputParameters()是处理存储过程输出参数的
    public interface ResultSetHandler {

    List handleResultSets(Statement stmt) throws SQLException;

    Cursor handleCursorResultSets(Statement stmt) throws SQLException;

    void handleOutputParameters(CallableStatement cs) throws SQLException;

    }

    Mybatis提供了默认的ResultSetHandler实现类DefaultResultSetHandler,其中重点是handlerResultSets()的实现
    @Override
    public List handleResultSets(Statement stmt) throws SQLException {
    ErrorContext.instance().activity(“handling results”).object(mappedStatement.getId());

    final List multipleResults = new ArrayList<>();

    int resultSetCount = 0;
    ResultSetWrapper rsw = getFirstResultSet(stmt);

    List resultMaps = mappedStatement.getResultMaps();
    int resultMapCount = resultMaps.size();
    validateResultMapsCount(rsw, resultMapCount);
    while (rsw != null && resultMapCount > resultSetCount) {
    ResultMap resultMap = resultMaps.get(resultSetCount);
    handleResultSet(rsw, resultMap, multipleResults, null);
    rsw = getNextResultSet(stmt);
    cleanUpAfterHandlingResultSet();
    resultSetCount++;
    }

    String[] resultSets = mappedStatement.getResultSets();
    if (resultSets != null) {
    while (rsw != null && resultSetCount < resultSets.length) { ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]); if (parentMapping != null) { String nestedResultMapId = parentMapping.getNestedResultMapId(); ResultMap resultMap = configuration.getResultMap(nestedResultMapId); handleResultSet(rsw, resultMap, null, parentMapping); } rsw = getNextResultSet(stmt); cleanUpAfterHandlingResultSet(); resultSetCount++; } } return collapseSingleResultList(multipleResults); } 在Executor中doQuery()方法返回了封装的结果集 @Override public List doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
    Statement stmt = null;
    try {
    Configuration configuration = ms.getConfiguration();
    StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
    stmt = prepareStatement(handler, ms.getStatementLog());
    return handler.query(stmt, resultHandler);
    } finally {
    closeStatement(stmt);
    }
    }

    实际上是返回结果是调用了resultSetHandler的handleResultSets()方法
    @Override
    public List query(Statement statement, ResultHandler resultHandler) throws SQLException {
    String sql = boundSql.getSql();
    statement.execute(sql);
    return resultSetHandler.handleResultSets(statement);
    }

  • ResultSetHandler接口,handlerResultSets()是包装并返回结果集的,handleOutputParameters()是处理存储过程输出参数的
    public interface ResultSetHandler {

    List handleResultSets(Statement stmt) throws SQLException;

    Cursor handleCursorResultSets(Statement stmt) throws SQLException;

    void handleOutputParameters(CallableStatement cs) throws SQLException;

    }

  • Mybatis提供了默认的ResultSetHandler实现类DefaultResultSetHandler,其中重点是handlerResultSets()的实现
    @Override
    public List handleResultSets(Statement stmt) throws SQLException {
    ErrorContext.instance().activity(“handling results”).object(mappedStatement.getId());

    final List multipleResults = new ArrayList<>();

    int resultSetCount = 0;
    ResultSetWrapper rsw = getFirstResultSet(stmt);

    List resultMaps = mappedStatement.getResultMaps();
    int resultMapCount = resultMaps.size();
    validateResultMapsCount(rsw, resultMapCount);
    while (rsw != null && resultMapCount > resultSetCount) {
    ResultMap resultMap = resultMaps.get(resultSetCount);
    handleResultSet(rsw, resultMap, multipleResults, null);
    rsw = getNextResultSet(stmt);
    cleanUpAfterHandlingResultSet();
    resultSetCount++;
    }

    String[] resultSets = mappedStatement.getResultSets();
    if (resultSets != null) {
    while (rsw != null && resultSetCount < resultSets.length) { ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]); if (parentMapping != null) { String nestedResultMapId = parentMapping.getNestedResultMapId(); ResultMap resultMap = configuration.getResultMap(nestedResultMapId); handleResultSet(rsw, resultMap, null, parentMapping); } rsw = getNextResultSet(stmt); cleanUpAfterHandlingResultSet(); resultSetCount++; } } return collapseSingleResultList(multipleResults); }

  • 在Executor中doQuery()方法返回了封装的结果集
    @Override
    public List doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
    Statement stmt = null;
    try {
    Configuration configuration = ms.getConfiguration();
    StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
    stmt = prepareStatement(handler, ms.getStatementLog());
    return handler.query(stmt, resultHandler);
    } finally {
    closeStatement(stmt);
    }
    }

  • 实际上是返回结果是调用了resultSetHandler的handleResultSets()方法
    @Override
    public List query(Statement statement, ResultHandler resultHandler) throws SQLException {
    String sql = boundSql.getSql();
    statement.execute(sql);
    return resultSetHandler.handleResultSets(statement);
    }

  • ————————

    Mybatis执行原理初探

    初始化

    • 加载配置文件
      String resource = “mybatis.xml”;

      // 加载mybatis的配置文件(它也加载关联的映射文件)
      InputStream inputStream = null;
      try {
      inputStream = Resources.getResourceAsStream(resource);
      } catch (IOException e) {
      e.printStackTrace();
      }

    • 构建sqlsession工厂
      // 构建sqlSession的工厂
      sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

    • SqlSessionFactoryBuilder类中build方法
      // SqlSessionFactoryBuilder类
      public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
      try {
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      return build(parser.parse()); // 开始进行解析了 🙂
      } catch (Exception e) {
      throw ExceptionFactory.wrapException(“Error building SqlSession.”, e);
      } finally {
      ErrorContext.instance().reset();
      try {
      inputStream.close();
      } catch (IOException e) {
      // Intentionally ignore. Prefer previous error.
      }
      }
      }

    • XMLConfigBuilder类的parse方法解析配置文件和mapper文件,生成configuration
      // XMLConfigBuilder类
      public Configuration parse() {
      if (parsed) {
      throw new BuilderException(“Each XMLConfigBuilder can only be used once.”);
      }
      parsed = true;
      parseConfiguration(parser.evalNode(“/configuration”));
      return configuration;
      }

      private void parseConfiguration(XNode root) {
      try {
      //issue #117 read properties first
      propertiesElement(root.evalNode(“properties”));
      Properties settings = settingsAsProperties(root.evalNode(“settings”));
      loadCustomVfs(settings);
      typeAliasesElement(root.evalNode(“typeAliases”));
      pluginElement(root.evalNode(“plugins”));
      objectFactoryElement(root.evalNode(“objectFactory”));
      objectWrapperFactoryElement(root.evalNode(“objectWrapperFactory”));
      reflectorFactoryElement(root.evalNode(“reflectorFactory”));
      settingsElement(settings);
      // read it after objectFactory and objectWrapperFactory issue #631

      /* 处理environments节点数据 */
      environmentsElement(root.evalNode(“environments”));
      databaseIdProviderElement(root.evalNode(“databaseIdProvider”));
      typeHandlerElement(root.evalNode(“typeHandlers”));
      mapperElement(root.evalNode(“mappers”));
      } catch (Exception e) {
      throw new BuilderException(“Error parsing SQL Mapper Configuration. Cause: ” + e, e);
      }
      }

    • SqlSessionFactoryBuilder类的build(configuration)方法得到XMLConfigBuilder的parse()方法的返回值configuration生成DefaultSqlSessionFactory,初始化完成
      // SqlSessionFactoryBuilder类
      public SqlSessionFactory build(Configuration config) {
      return new DefaultSqlSessionFactory(config);
      }

    SqlSession

    四个重要的对象

    1.Executor执行器

    调度执行StatmentHandler、ParameterHandler、ResultHandler执行相应的SQL语句
    • Executor执行器有三种:简易执行器SIMPLE(不配置就是默认执行器)、REUSE是一种重用预处理语句、BATCH批量更新、批量专用处理器
    • 执行器的作用:Executor会先调用StatementHandler的prepare()方法预编译SQL语句,同时设置一些基本的运行参数,然后调用StatementHandler的parameterize()方法(实际上是启用了ParameterHandler设置参数)设置参数,resultHandler再组装查询结果返回调用者完成一次查询完成预编译,简单总结起来就是即先预编译SQL语句,之后设置参数(跟JDBC的prepareStatement过程类似)最后如果有查询结果就会组装返回
    • Executor源码:

      executor的来历:Configuration类的newExecutor()方法(下文举例返回SimpleExecutor对象)
      //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;
      }

      SimpleExecutor继承了BaseExecuror抽象类,BaseExecurot实现了Executor接口,simpleExecutor只有一个prepareStatement方法,其他方法均来自抽象类BaseExecutor
      public class SimpleExecutor extends BaseExecutor
      public abstract class BaseExecutor implements Executor

      调用prepareStatement()方法,在其中调用StatementHandler的prepare()和parameterize()方法
      //SimpleExecutor类
      private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
      Statement stmt;
      Connection connection = getConnection(statementLog);
      stmt = handler.prepare(connection, transaction.getTimeout());
      handler.parameterize(stmt);
      return stmt;
      }

    • executor的来历:Configuration类的newExecutor()方法(下文举例返回SimpleExecutor对象)
      //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;
      }

    • SimpleExecutor继承了BaseExecuror抽象类,BaseExecurot实现了Executor接口,simpleExecutor只有一个prepareStatement方法,其他方法均来自抽象类BaseExecutor
      public class SimpleExecutor extends BaseExecutor
      public abstract class BaseExecutor implements Executor
    • 调用prepareStatement()方法,在其中调用StatementHandler的prepare()和parameterize()方法
      //SimpleExecutor类
      private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
      Statement stmt;
      Connection connection = getConnection(statementLog);
      stmt = handler.prepare(connection, transaction.getTimeout());
      handler.parameterize(stmt);
      return stmt;
      }

    2.StatamentHandler数据库会话器

    使用数据库中Statement(PrepareStatement)执行操作,即底层是封装好了的prepareStatement
    • 作用:
      简单来说就是专门处理数据库会话。详细来说就是进行预编译并且调用ParameterHandler的setParameters()方法设置参数
    • StatementHandler有三种:
      SimpleStatementHandler、PrepareStatementHandler、CallableStatementHandler,分别对应Executor的三种执行器(SIMPLE、REUSE、BATCH)
    • StatementHandler源码

      来源:Configuration类中的newStatementHandler()方法,返回的实际是实现了StatementHandler接口的RoutingStatementHandler类
      //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;
      }

      RoutingStatementHandler根据传入的Executor执行器类型返回不同类型的StatementHandler(下文以SimpleStatementHandler为例)
      //RoutingStatementHandler类
      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());
      }

      }

      SimpleStatementHandler类继承了抽象类BaseStatementHandler实现了StatementHandler接口
      public class SimpleStatementHandler extends BaseStatementHandler
      public abstract class BaseStatementHandler implements StatementHandler

      在BaseStatementHandler中重写prepare()方法,instantiateStatement()方法完成预编译,之后设置一些基础配置(获取最大行数,超时)
      @Override
      public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
      ErrorContext.instance().sql(boundSql.getSql());
      Statement statement = null;
      try {
      statement = instantiateStatement(connection);
      setStatementTimeout(statement, transactionTimeout);
      setFetchSize(statement);
      return statement;
      } catch (SQLException e) {
      closeStatement(statement);
      throw e;
      } catch (Exception e) {
      closeStatement(statement);
      throw new ExecutorException(“Error preparing statement. Cause: ” + e, e);
      }
      }

      *instantiateStatement*()预编译实际上也是使用了JDBC的prepareStatement()完成预编译
      @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 {
      return connection.prepareStatement(sql);
      }
      }

      parameterize()方法实际上调用了PreparedStatementHandler类的ParameterHandler的setParameters()方法
      @Override
      public void parameterize(Statement statement) throws SQLException {
      parameterHandler.setParameters((PreparedStatement) statement);
      }

    • 来源:Configuration类中的newStatementHandler()方法,返回的实际是实现了StatementHandler接口的RoutingStatementHandler类
      //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;
      }

      RoutingStatementHandler根据传入的Executor执行器类型返回不同类型的StatementHandler(下文以SimpleStatementHandler为例)
      //RoutingStatementHandler类
      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());
      }

      }

    • SimpleStatementHandler类继承了抽象类BaseStatementHandler实现了StatementHandler接口
      public class SimpleStatementHandler extends BaseStatementHandler
      public abstract class BaseStatementHandler implements StatementHandler
    • 在BaseStatementHandler中重写prepare()方法,instantiateStatement()方法完成预编译,之后设置一些基础配置(获取最大行数,超时)
      @Override
      public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
      ErrorContext.instance().sql(boundSql.getSql());
      Statement statement = null;
      try {
      statement = instantiateStatement(connection);
      setStatementTimeout(statement, transactionTimeout);
      setFetchSize(statement);
      return statement;
      } catch (SQLException e) {
      closeStatement(statement);
      throw e;
      } catch (Exception e) {
      closeStatement(statement);
      throw new ExecutorException(“Error preparing statement. Cause: ” + e, e);
      }
      }

    • *instantiateStatement*()预编译实际上也是使用了JDBC的prepareStatement()完成预编译
      @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 {
      return connection.prepareStatement(sql);
      }
      }

    • parameterize()方法实际上调用了PreparedStatementHandler类的ParameterHandler的setParameters()方法
      @Override
      public void parameterize(Statement statement) throws SQLException {
      parameterHandler.setParameters((PreparedStatement) statement);
      }

    3.ParameterHandler

    处理Sql参数
    • 作用:对预编译中参数进行设置,如果有配置typeHandler,自然会对注册的typeHandler对参数进行处理
    • 源码

      Mybatis提供了ParamterHandler的默认实现类DefalutParameterHandler
      public interface ParameterHandler {

      Object getParameterObject();

      void setParameters(PreparedStatement ps) throws SQLException;

      }

      public class DefaultParameterHandler implements ParameterHandler
      ParameterHandler接口中的getParameterObject()方法是返回参数对象,setParameters()是设置预编译参数
      @Override
      public Object getParameterObject() {
      return parameterObject;
      }

      从parameterObject中取到参数,然后使用typeHandler(注册在Configuration中)进行参数处理:
      @Override
      public void setParameters(PreparedStatement ps) {
      ErrorContext.instance().activity(“setting parameters”).object(mappedStatement.getParameterMap().getId());
      List parameterMappings = boundSql.getParameterMappings();
      if (parameterMappings != null) {
      for (int i = 0; i < parameterMappings.size(); i++) { ParameterMapping parameterMapping = parameterMappings.get(i); if (parameterMapping.getMode() != ParameterMode.OUT) { Object value; String propertyName = parameterMapping.getProperty(); if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params value = boundSql.getAdditionalParameter(propertyName); } else if (parameterObject == null) { value = null; } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) { value = parameterObject; } else { MetaObject metaObject = configuration.newMetaObject(parameterObject); value = metaObject.getValue(propertyName); } TypeHandler typeHandler = parameterMapping.getTypeHandler(); JdbcType jdbcType = parameterMapping.getJdbcType(); if (value == null && jdbcType == null) { jdbcType = configuration.getJdbcTypeForNull(); } try { typeHandler.setParameter(ps, i + 1, value, jdbcType); } catch (TypeException | SQLException e) { throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e); } } } } }

    • Mybatis提供了ParamterHandler的默认实现类DefalutParameterHandler
      public interface ParameterHandler {

      Object getParameterObject();

      void setParameters(PreparedStatement ps) throws SQLException;

      }

      public class DefaultParameterHandler implements ParameterHandler
      ParameterHandler接口中的getParameterObject()方法是返回参数对象,setParameters()是设置预编译参数
      @Override
      public Object getParameterObject() {
      return parameterObject;
      }

    • 从parameterObject中取到参数,然后使用typeHandler(注册在Configuration中)进行参数处理:
      @Override
      public void setParameters(PreparedStatement ps) {
      ErrorContext.instance().activity(“setting parameters”).object(mappedStatement.getParameterMap().getId());
      List parameterMappings = boundSql.getParameterMappings();
      if (parameterMappings != null) {
      for (int i = 0; i < parameterMappings.size(); i++) { ParameterMapping parameterMapping = parameterMappings.get(i); if (parameterMapping.getMode() != ParameterMode.OUT) { Object value; String propertyName = parameterMapping.getProperty(); if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params value = boundSql.getAdditionalParameter(propertyName); } else if (parameterObject == null) { value = null; } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) { value = parameterObject; } else { MetaObject metaObject = configuration.newMetaObject(parameterObject); value = metaObject.getValue(propertyName); } TypeHandler typeHandler = parameterMapping.getTypeHandler(); JdbcType jdbcType = parameterMapping.getJdbcType(); if (value == null && jdbcType == null) { jdbcType = configuration.getJdbcTypeForNull(); } try { typeHandler.setParameter(ps, i + 1, value, jdbcType); } catch (TypeException | SQLException e) { throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e); } } } } }

    4.ResultSetHandler结果集处理器:

    结果集ResultSet封装处理返回
    • 作用:组装结果返回结果集
    • 源码:

      ResultSetHandler接口,handlerResultSets()是包装并返回结果集的,handleOutputParameters()是处理存储过程输出参数的
      public interface ResultSetHandler {

      List handleResultSets(Statement stmt) throws SQLException;

      Cursor handleCursorResultSets(Statement stmt) throws SQLException;

      void handleOutputParameters(CallableStatement cs) throws SQLException;

      }

      Mybatis提供了默认的ResultSetHandler实现类DefaultResultSetHandler,其中重点是handlerResultSets()的实现
      @Override
      public List handleResultSets(Statement stmt) throws SQLException {
      ErrorContext.instance().activity(“handling results”).object(mappedStatement.getId());

      final List multipleResults = new ArrayList<>();

      int resultSetCount = 0;
      ResultSetWrapper rsw = getFirstResultSet(stmt);

      List resultMaps = mappedStatement.getResultMaps();
      int resultMapCount = resultMaps.size();
      validateResultMapsCount(rsw, resultMapCount);
      while (rsw != null && resultMapCount > resultSetCount) {
      ResultMap resultMap = resultMaps.get(resultSetCount);
      handleResultSet(rsw, resultMap, multipleResults, null);
      rsw = getNextResultSet(stmt);
      cleanUpAfterHandlingResultSet();
      resultSetCount++;
      }

      String[] resultSets = mappedStatement.getResultSets();
      if (resultSets != null) {
      while (rsw != null && resultSetCount < resultSets.length) { ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]); if (parentMapping != null) { String nestedResultMapId = parentMapping.getNestedResultMapId(); ResultMap resultMap = configuration.getResultMap(nestedResultMapId); handleResultSet(rsw, resultMap, null, parentMapping); } rsw = getNextResultSet(stmt); cleanUpAfterHandlingResultSet(); resultSetCount++; } } return collapseSingleResultList(multipleResults); } 在Executor中doQuery()方法返回了封装的结果集 @Override public List doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
      Statement stmt = null;
      try {
      Configuration configuration = ms.getConfiguration();
      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
      stmt = prepareStatement(handler, ms.getStatementLog());
      return handler.query(stmt, resultHandler);
      } finally {
      closeStatement(stmt);
      }
      }

      实际上是返回结果是调用了resultSetHandler的handleResultSets()方法
      @Override
      public List query(Statement statement, ResultHandler resultHandler) throws SQLException {
      String sql = boundSql.getSql();
      statement.execute(sql);
      return resultSetHandler.handleResultSets(statement);
      }

    • ResultSetHandler接口,handlerResultSets()是包装并返回结果集的,handleOutputParameters()是处理存储过程输出参数的
      public interface ResultSetHandler {

      List handleResultSets(Statement stmt) throws SQLException;

      Cursor handleCursorResultSets(Statement stmt) throws SQLException;

      void handleOutputParameters(CallableStatement cs) throws SQLException;

      }

    • Mybatis提供了默认的ResultSetHandler实现类DefaultResultSetHandler,其中重点是handlerResultSets()的实现
      @Override
      public List handleResultSets(Statement stmt) throws SQLException {
      ErrorContext.instance().activity(“handling results”).object(mappedStatement.getId());

      final List multipleResults = new ArrayList<>();

      int resultSetCount = 0;
      ResultSetWrapper rsw = getFirstResultSet(stmt);

      List resultMaps = mappedStatement.getResultMaps();
      int resultMapCount = resultMaps.size();
      validateResultMapsCount(rsw, resultMapCount);
      while (rsw != null && resultMapCount > resultSetCount) {
      ResultMap resultMap = resultMaps.get(resultSetCount);
      handleResultSet(rsw, resultMap, multipleResults, null);
      rsw = getNextResultSet(stmt);
      cleanUpAfterHandlingResultSet();
      resultSetCount++;
      }

      String[] resultSets = mappedStatement.getResultSets();
      if (resultSets != null) {
      while (rsw != null && resultSetCount < resultSets.length) { ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]); if (parentMapping != null) { String nestedResultMapId = parentMapping.getNestedResultMapId(); ResultMap resultMap = configuration.getResultMap(nestedResultMapId); handleResultSet(rsw, resultMap, null, parentMapping); } rsw = getNextResultSet(stmt); cleanUpAfterHandlingResultSet(); resultSetCount++; } } return collapseSingleResultList(multipleResults); }

    • 在Executor中doQuery()方法返回了封装的结果集
      @Override
      public List doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
      Statement stmt = null;
      try {
      Configuration configuration = ms.getConfiguration();
      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
      stmt = prepareStatement(handler, ms.getStatementLog());
      return handler.query(stmt, resultHandler);
      } finally {
      closeStatement(stmt);
      }
      }

    • 实际上是返回结果是调用了resultSetHandler的handleResultSets()方法
      @Override
      public List query(Statement statement, ResultHandler resultHandler) throws SQLException {
      String sql = boundSql.getSql();
      statement.execute(sql);
      return resultSetHandler.handleResultSets(statement);
      }