work hard work smart

专注于Java后端开发。 不断总结,举一反三。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Mybatis原生源码解析

Posted on 2020-03-25 12:32  work hard work smart  阅读(218)  评论(0编辑  收藏  举报

原始的JDBC操作数据库,请参考Java JDBC连接Oracle

一、工程搭建

工程结构如下

 

 

1、引入jar  mybatis-3.2.3.jar 和mysql-connector-java-5.1.25.bin.jar

2、使用Mysql创建表

CREATE TABLE `user` (
  `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(64) NOT NULL DEFAULT '',
  `dept` VARCHAR(254) NOT NULL DEFAULT '',
  `website` VARCHAR(254) DEFAULT '',
  `phone` VARCHAR(16) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=2 ;


INSERT INTO `user` VALUES ('1', 'larry', 'IT', 'http://www.baidu.com', '13688889999');

  

3、创建User实体类

public class User {
    private int id;
    private String name;
    private String dept;
    private String phone;
    private String website;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDept() {
        return dept;
    }

    public void setDept(String dept) {
        this.dept = dept;
    }

    public String getPhone() {
        return phone;
    }

    public void setPhone(String phone) {
        this.phone = phone;
    }

    public String getWebsite() {
        return website;
    }

    public void setWebsite(String website) {
        this.website = website;
    }
}

  

4、resources/configs/下创建Configure.xml

mybatis 配置文件,用来建立sessionFactory。里面主要包含了数据库连接,还有Java类对应的别名

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <typeAlias alias="User2" type="com.example.mybatis.model.User" />
    </typeAliases>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"></transactionManager>
            <dataSource type="POOLED">
                <property name="driver"  value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="123456"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mapper/User.xml" />
    </mappers>
</configuration>  

这里<mapper resource="mapper/User.xml" /> 要映射类的xml配置文件

 

5、resources/mapper下创建User.xml

包含了各种SQL语句

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mybatis.dao.UserMapper">
    <select id="getUserById" parameterType="int" resultType="User2">
        select * from user where id = #{id}
    </select>
</mapper>

  

6、创建接口com.example.mybatis.dao.UserMapper

public interface UserMapper {
    User getUserById(int id);
}

  

7、创建测试类

public class MyBatisTest1 {

    private static SqlSessionFactory sqlSessionFactory;
    private static Reader reader;

    static {
        try {
            reader = Resources.getResourceAsReader("config/Configure.xml");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public static  SqlSessionFactory getSession(){
        return  sqlSessionFactory;
    }

    public static void main(String[] args) {
        SqlSession session = sqlSessionFactory.openSession();
        try {
           User user =  (User)session.selectOne("com.example.mybatis.dao.UserMapper.getUserById",1 ) ;
           if(user != null){
               System.out.println("name is : " + user.getName() + ",所属部门: " + user.getDept());
           }
        }finally {
            session.close();
        }
    }
}

  

8、显示

 

二、源码解析

通过前面的步骤,关键步骤如下

  // 1.读取mybatis配置文件,并生成SQLSessionFactory
 reader = Resources.getResourceAsReader("config/Configure.xml");
  // 2.获取session,主要的CRUD操作均在SqlSession中提供
  SqlSession session = sqlSessionFactory.openSession();
 // 3.执行查询操作
  // 该方法包括三个步骤:封装入参数、执行查询、封装结果为对象类型
  User user =  (User)session.selectOne("com.example.mybatis.dao.UserMapper.getUserById",1 ) ;

 

1、 Resources.getResourceAsReader("config/Configure.xml");

public static Reader getResourceAsReader(String resource) throws IOException {
        InputStreamReader reader;
	//默认为null
        if (charset == null) {
            reader = new InputStreamReader(getResourceAsStream(resource));
        } else {
            reader = new InputStreamReader(getResourceAsStream(resource), charset);
        }

        return reader;
    }

    //getResourceAsStream方法
    public static InputStream getResourceAsStream(String resource) throws IOException {
        return getResourceAsStream((ClassLoader)null, resource);
    }
    
    //getResourceAsStream方法
    public static InputStream getResourceAsStream(ClassLoader loader, String resource) throws IOException {
        InputStream in = classLoaderWrapper.getResourceAsStream(resource, loader);
        if (in == null) {
            throw new IOException("Could not find resource " + resource);
        } else {
            return in;
        }
    }

   //ClassLoaderWrapper.getResourceAsStream方法
  InputStream getResourceAsStream(String resource, ClassLoader[] classLoader) {
    for (ClassLoader cl : classLoader) {
      if (null != cl) {

        // 获得资源
        InputStream returnValue = cl.getResourceAsStream(resource);

        // now, some class loaders want this leading "/", so we'll add it and try again if we didn't find the resource
        if (null == returnValue) returnValue = cl.getResourceAsStream("/" + resource);

        if (null != returnValue) return returnValue;
      }
    }
    return null;
  }

  

总结:通过ClassLoader.getResourceAsStream()获取指定路径下的Resource

 

 

2、获取sqlSessionFactory 

  sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);  
  //build方法
  public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
    try {
      XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
      //重点是这个方法 实现了parser.parse()解析xml,build创建sqlSessionFactory
      return build(parser.parse());
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error building SqlSession.", e);
    } finally {
      ErrorContext.instance().reset();
      try {
        reader.close();
      } catch (IOException e) {
        // Intentionally ignore. Prefer previous error.
      }
    }
  }

  

1) 首先是parser.parse()方法

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 {
      //是对各个节点进行解析
      propertiesElement(root.evalNode("properties")); //issue #117 read properties first
      typeAliasesElement(root.evalNode("typeAliases"));
      pluginElement(root.evalNode("plugins"));
      objectFactoryElement(root.evalNode("objectFactory"));
      objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
      settingsElement(root.evalNode("settings"));
      environmentsElement(root.evalNode("environments")); // read it after objectFactory and objectWrapperFactory issue #631
      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);
    }
  }


private void mapperElement(XNode parent) throws Exception {
    if (parent != null) {
      for (XNode child : parent.getChildren()) {
        if ("package".equals(child.getName())) {
          String mapperPackage = child.getStringAttribute("name");
          configuration.addMappers(mapperPackage);
        } else {
	  //1、获得resource信息,也就是对应的mapper.xml,这里是mapper/User.xml
          String resource = child.getStringAttribute("resource");
          String url = child.getStringAttribute("url");
          String mapperClass = child.getStringAttribute("class");
          if (resource != null && url == null && mapperClass == null) {
	    //2.解析对应的User.xml
            ErrorContext.instance().resource(resource);
            InputStream inputStream = Resources.getResourceAsStream(resource);
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
	    //3、将解析出来的Mapper对象添加到Configuration中
            mapperParser.parse();
          } else if (resource == null && url != null && mapperClass == null) {
            ErrorContext.instance().resource(url);
            InputStream inputStream = Resources.getUrlAsStream(url);
            XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
            mapperParser.parse();
          } else if (resource == null && url == null && mapperClass != null) {
            Class<?> mapperInterface = Resources.classForName(mapperClass);
            configuration.addMapper(mapperInterface);
          } else {
            throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
          }
        }
      }
    }
  }

  总结:通过解析configuration.xml文件,获取其中的Environment、Setting,mappers下的所有<mapper>解析出来之后添加到Configuration。

 

2)、生成一个SQLSessionFactory

public SqlSessionFactory build(Configuration config) {

return new DefaultSqlSessionFactory(config);

}
   

  

3、sqlSessionFactory.openSession(); 开启一个sqlSession

  public SqlSession openSession() {
    return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
  }

  private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
      final Environment environment = configuration.getEnvironment();
      //1、transactionFactory,这里为JdbcTransactionFactory
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      //2、创建一个transaction
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
      //3、创建一个Executor 这里为SimpleExecutor,主要的CRUD操作就是再此处完成的
      final Executor executor = configuration.newExecutor(tx, execType, autoCommit);
      //4、将Executor和configuration作为参数,封装到DefaultSqlSession
      return new DefaultSqlSession(configuration, executor);
    } catch (Exception e) {
      closeTransaction(tx); // may have fetched a connection so lets call close()
      throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }

  

1) TransactionFactory ,主要用来生成transaction的工厂

public interface TransactionFactory {
  void setProperties(Properties props);
  Transaction newTransaction(Connection conn);
  Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit);

}

  

2) Transaction

public interface Transaction {
  Connection getConnection() throws SQLException;
  void commit() throws SQLException;
  void rollback() throws SQLException;
  void close() throws SQLException;
}  

可以看到getConnection() 就是返回的java.sql.Connection, 并且还有commint和rollback等操作

 3)Executor

该接口定义了CRUD操作

public interface Executor {

  ResultHandler NO_RESULT_HANDLER = null;

  int update(MappedStatement ms, Object parameter) throws SQLException;

  <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;

  <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;

  List<BatchResult> flushStatements() throws SQLException;

  void commit(boolean required) throws SQLException;

  void rollback(boolean required) throws SQLException;

  CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql);

  boolean isCached(MappedStatement ms, CacheKey key);

  void clearLocalCache();

  void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType);

  Transaction getTransaction();

  void close(boolean forceRollback);

  boolean isClosed();

}

  

4、session.selectOne的执行过程

 public <T> T selectOne(String statement, Object parameter) {
    // 调用selectList
    List<T> list = this.<T>selectList(statement, parameter);
    if (list.size() == 1) {
      return list.get(0);
    } else if (list.size() > 1) {
      throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
    } else {
      return null;
    }
  }



  public <E> List<E> selectList(String statement, Object parameter) {
    return this.selectList(statement, parameter, RowBounds.DEFAULT);
  }

  public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
    try {
      //1、获取MappedStatement,里面封装了每一个CRUD操作对应的详细信息 
      MappedStatement ms = configuration.getMappedStatement(statement);
      //2、executor的实现类为CachingExecutor
      List<E> result = executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
      return result;
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }

  

5、CachingExecutor.query方法

 public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
    BoundSql boundSql = ms.getBoundSql(parameterObject);
    CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
    return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
  }

  public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    Cache cache = ms.getCache();
    if (cache != null) {
      flushCacheIfRequired(ms);
      if (ms.isUseCache() && resultHandler == null) { 
        ensureNoOutParams(ms, parameterObject, boundSql);
        if (!dirty) {
          cache.getReadWriteLock().readLock().lock();
          try {
            @SuppressWarnings("unchecked")
            List<E> cachedList = (List<E>) cache.getObject(key);
            if (cachedList != null) return cachedList;
          } finally {
            cache.getReadWriteLock().readLock().unlock();
          }
        }
        List<E> list = delegate.<E> query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
        tcm.putObject(cache, key, list); // issue #578. Query must be not synchronized to prevent deadlocks
        return list;
      }
    }
    //重点是这句,默认实现为BaseExecutor
    return delegate.<E>query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
  }


//BaseExecutor的query方法
  public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
    if (closed) throw new ExecutorException("Executor was closed.");
    if (queryStack == 0 && ms.isFlushCacheRequired()) {
      clearLocalCache();
    }
    List<E> list;
    try {
      queryStack++;
      list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
      if (list != null) {
        handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
      } else {
	//重点是这里
        list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
      }
    } finally {
      queryStack--;
    }
    if (queryStack == 0) {
      for (DeferredLoad deferredLoad : deferredLoads) {
        deferredLoad.load();
      }
      deferredLoads.clear(); // issue #601
      if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
        clearLocalCache(); // issue #482
      }
    }
    return list;
  }




  private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
    List<E> list;
    localCache.putObject(key, EXECUTION_PLACEHOLDER);
    try {
      //重点是这里,是一个抽象方法,由SimpleExecutor实现
      list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
    } finally {
      localCache.removeObject(key);
    }
    localCache.putObject(key, list);
    if (ms.getStatementType() == StatementType.CALLABLE) {
      localOutputParameterCache.putObject(key, parameter);
    }
    return list;
  }


//SimpleExecutor的doQuery方法
  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();
       //1、StatementHandler 分装了JDBC Statement操作,如设置参数,将Statement结果转换成List集合
      StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, rowBounds, resultHandler, boundSql);
      //2、封装StatementHandler 参数
      stmt = prepareStatement(handler, ms.getStatementLog());
      //执行execute操作
      return handler.<E>query(stmt, resultHandler);
    } finally {
      closeStatement(stmt);
    }
  }

  1) configuration.newStatementHandler

  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构造方法
  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());
    }

  }

  

 2) prepareStatement

功能: 获取Statement; 封装PreparedStatement参数

  private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
    Statement stmt;
    //1、获取java.sql.Connection
    Connection connection = getConnection(statementLog);
    //2、获取对应的statement
    stmt = handler.prepare(connection);
    //3、封装参数
    handler.parameterize(stmt);
    return stmt;
  }

  

*进入handler.prepare(connection)获取Statement

//BaseStatementHandler.prepare
  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) {
      closeStatement(statement);
      throw e;
    } catch (Exception e) {
      closeStatement(statement);
      throw new ExecutorException("Error preparing statement.  Cause: " + e, e);
    }
  }

//BaseStatementHandler.instantiateStatement
  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 {
      //默认实现,直接对应传统JDBC方式的从connection中获取PreparedStatement
      return connection.prepareStatement(sql);
    }
  }

  

* handler.parameterize(stmt);封装参数

  public void parameterize(Statement statement) throws SQLException {
    delegate.parameterize(statement);
  }

  public void parameterize(Statement statement) throws SQLException {
    parameterHandler.setParameters((PreparedStatement) statement);
  }


public void setParameters(PreparedStatement ps) throws SQLException {
    ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
    //1、parameterMappings 包含了需要拼装的参数
    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    if (parameterMappings != null) {
      MetaObject metaObject = parameterObject == null ? null : configuration.newMetaObject(parameterObject);
      for (int i = 0; i < parameterMappings.size(); i++) {
        ParameterMapping parameterMapping = parameterMappings.get(i);
        if (parameterMapping.getMode() != ParameterMode.OUT) {
          Object value;
	  //2、获取参数名称
          String propertyName = parameterMapping.getProperty();
          //3、获取参数值
	  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 {
            value = metaObject == null ? null : metaObject.getValue(propertyName);
          }
	  //4、获取参数对应的类型处理器
          TypeHandler typeHandler = parameterMapping.getTypeHandler();
          JdbcType jdbcType = parameterMapping.getJdbcType();
          if (value == null && jdbcType == null) jdbcType = configuration.getJdbcTypeForNull();
          //5、对应的封装参数操作还是委托给TypeHandle处理
	  typeHandler.setParameter(ps, i + 1, value, jdbcType);
        }
      }
    }
  }


//BaseTypeHandler.setParameter
  public void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
    if (parameter == null) {
      if (jdbcType == null) {
        throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters.");
      }
      try {
        ps.setNull(i, jdbcType.TYPE_CODE);
      } catch (SQLException e) {
        throw new TypeException("Error setting null for parameter #" + i + " with JdbcType " + jdbcType + " . " +
        		"Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. " +
        		"Cause: " + e, e);
      }
    } else {
      //由于参数非空,走这个方法。setNonNullParameter是抽象方法,由子类实现
      setNonNullParameter(ps, i, parameter, jdbcType);
    }
  }

  

这里的参数类型为int,对应的实现类为为IntegerTypeHandler

  @Override
  public void setNonNullParameter(PreparedStatement ps, int i, Integer parameter, JdbcType jdbcType)
      throws SQLException {
    ps.setInt(i, parameter);
  }  

对应JDBC的处理为preparedStatement.setInt(index,value)

经过上面的分析,最终处理还是JDBC那一套。通过connection创建preparedStatement;对preparedStatement进行参数封装;

 

 

3) handler.<E>query(stmt, resultHandler);

  public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
    return delegate.<E>query(statement, resultHandler);
  }

//PreparedStatementHandler.query()
  public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
    PreparedStatement ps = (PreparedStatement) statement;
    //1、执行execute操作
    ps.execute();
    //2、对结果进行封装
    return resultSetHandler.<E> handleResultSets(ps);
  }

  

总结:mybatis操作流程如下

1) 解析configuration.xml,生成Environment、Setting、Mapper等对象,并注册到Configuration

2) 从SqlSessionFactory中获取SqlSession,SqlSession作为操作入口,接收用户的数据库操作,并委托给内部的Executor来实现

3) Executor内部StatementHandler负责Statement的创建;PreparedStatement参数的注入;execute方法的执行
4) execute方法执行,ResultSetHandler进行结果的封装

参考:原生Mybatis框架源码解析