该篇主要讲解的是mybatis从seesion创建到执行sql语句的流程

流程主线:

1.创建SqlSessionFactoryBuilder

2.创建会话工厂SqlSessionFactory

3.创建执行实例Executor(实现类有BatchExecutor,ReuseExecutor,SimpleExecutor以及CachingExecutor)

4.创建会话SqlSession

5. 创建执行器StatementHandler(实现类有SimpleStatementHandler,CallableStatementHandler,PreparedStatementHandler以及RoutingStatementHandler)

6.执行JDBC操作

SqlSessionFactoryBuilder

public class SqlSessionFactoryBuilder {
  //创建SqlSessionFactory
  public SqlSessionFactory build(Reader reader) {
    return build(reader, null, null);
  }
    //创建SqlSessionFactory
  public SqlSessionFactory build(Reader reader, String environment) {
    return build(reader, environment, null);
  }
  //创建SqlSessionFactory
  public SqlSessionFactory build(Reader reader, Properties properties) {
    return build(reader, null, properties);
  }
  //创建SqlSessionFactory
  public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
    try {      //解析配置文件
      XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
      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.
      }
    }
  }
  //创建SqlSessionFactory
  public SqlSessionFactory build(InputStream inputStream) {
    return build(inputStream, null, null);
  }
 //创建SqlSessionFactory
  public SqlSessionFactory build(InputStream inputStream, String environment) {
    return build(inputStream, environment, null);
  }
  //创建SqlSessionFactory
  public SqlSessionFactory build(InputStream inputStream, Properties properties) {
    return build(inputStream, null, properties);
  }
  //创建SqlSessionFactory
  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.
      }
    }
  }
  //创建SqlSessionFactory
  public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
  }

}

DefaultSqlSessionFactory

 private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
      final Environment environment = configuration.getEnvironment();
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);    //创建事务
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);      //创建执行实例
      final Executor executor = configuration.newExecutor(tx, execType);      //创建会话session
      return new DefaultSqlSession(configuration, executor, autoCommit);
    } 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();
    }
  }

  private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {
    try {
      boolean autoCommit;
      try {
        autoCommit = connection.getAutoCommit();
      } catch (SQLException e) {
        // Failover to true, as most poor drivers
        // or databases won't support transactions
        autoCommit = true;
      }
      final Environment environment = configuration.getEnvironment();
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);      //创建事务
      final Transaction tx = transactionFactory.newTransaction(connection);      //创建执行实例
      final Executor executor = configuration.newExecutor(tx, execType);      //创建会话session
      return new DefaultSqlSession(configuration, executor, autoCommit);
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }
创建执行实例
final Executor executor = configuration.newExecutor(tx, execType);
  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;
  }
 
创建会话session
new DefaultSqlSession(configuration, executor, autoCommit);
// 这里是一部分源码public class DefaultSqlSession implements SqlSession {
  //持有配置对象(内部就包含了sql语句的元数据)
  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 DefaultSqlSession(Configuration configuration, Executor executor) {
    this(configuration, executor, false);
  }

  public <T> T selectOne(String statement) {
    return this.<T>selectOne(statement, null);
  }

  public <T> T selectOne(String statement, Object parameter) {
    // Popular vote was to return null on 0 results and throw exception on too many.
    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;
    }
  }  //以下源码部分省略......
}

执行实例Executor持有执行器StatementHandler

以SimpleExecutor为例

public class SimpleExecutor extends BaseExecutor {

  public SimpleExecutor(Configuration configuration, Transaction transaction) {
    super(configuration, transaction);
  }

  public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
    Statement stmt = null;
    try {
      Configuration configuration = ms.getConfiguration();      //根据对应场景生成不同的执行器
      StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, null, null);
      stmt = prepareStatement(handler, ms.getStatementLog());
      return handler.update(stmt);
    } finally {
      closeStatement(stmt);
    }
  }

  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 handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
      stmt = prepareStatement(handler, ms.getStatementLog());
      return handler.<E>query(stmt, resultHandler);
    } finally {
      closeStatement(stmt);
    }
  }

  public List<BatchResult> doFlushStatements(boolean isRollback) throws SQLException {
    return Collections.emptyList();
  }
  //执行JDBC
  private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
    Statement stmt;
    Connection connection = getConnection(statementLog);
    stmt = handler.prepare(connection);
    handler.parameterize(stmt);
    return stmt;
  }

}
 

备注:

  如果自定义sql拦截器

  当我们需要改变sql的时候,显然我们要在预编译SQL(prepare方法前加入修改的逻辑)。

  当我们需要修改参数的时候我们可以在调用parameterize方法前修改逻辑。或者使用ParameterHandler来改造设置参数。

  我们需要控制组装结果集的时候,也可以在query方法前后加入逻辑,或者使用ResultHandler来改造组装结果。

 

												

mybatis工作流程&源码详解的更多相关文章

  1. Mybatis源码详解系列(四)--你不知道的Mybatis用法和细节

    简介 这是 Mybatis 系列博客的第四篇,我本来打算详细讲解 mybatis 的配置.映射器.动态 sql 等,但Mybatis官方中文文档对这部分内容的介绍已经足够详细了,有需要的可以直接参考. ...

  2. Java源码详解系列(十)--全面分析mybatis的使用、源码和代码生成器(总计5篇博客)

    简介 Mybatis 是一个持久层框架,它对 JDBC 进行了高级封装,使我们的代码中不会出现任何的 JDBC 代码,另外,它还通过 xml 或注解的方式将 sql 从 DAO/Repository ...

  3. Activiti架构分析及源码详解

    目录 Activiti架构分析及源码详解 引言 一.Activiti设计解析-架构&领域模型 1.1 架构 1.2 领域模型 二.Activiti设计解析-PVM执行树 2.1 核心理念 2. ...

  4. vue 源码详解(一):原型对象和全局 `API`的设计

    vue 源码详解(一):原型对象和全局 API的设计 1. 从 new Vue() 开始 我们在实际的项目中使用 Vue 的时候 , 一般都是在 main.js 中通过 new Vue({el : ' ...

  5. RocketMQ源码详解 | Consumer篇 · 其一:消息的 Pull 和 Push

    概述 当消息被存储后,消费者就会将其消费. 这句话简要的概述了一条消息的最总去向,也引出了本文将讨论的问题: 消息什么时候才对被消费者可见? 是在 page cache 中吗?还是在落盘后?还是像 K ...

  6. spring事务详解(三)源码详解

    系列目录 spring事务详解(一)初探事务 spring事务详解(二)简单样例 spring事务详解(三)源码详解 spring事务详解(四)测试验证 spring事务详解(五)总结提高 一.引子 ...

  7. saltstack源码详解一

    目录 初识源码流程 入口 1.grains.items 2.pillar.items 2/3: 是否可以用python脚本实现 总结pillar源码分析: @(python之路)[saltstack源 ...

  8. Shiro 登录认证源码详解

    Shiro 登录认证源码详解 Apache Shiro 是一个强大且灵活的 Java 开源安全框架,拥有登录认证.授权管理.企业级会话管理和加密等功能,相比 Spring Security 来说要更加 ...

  9. 源码详解系列(六) ------ 全面讲解druid的使用和源码

    简介 druid是用于创建和管理连接,利用"池"的方式复用连接减少资源开销,和其他数据源一样,也具有连接数控制.连接可靠性测试.连接泄露控制.缓存语句等功能,另外,druid还扩展 ...

随机推荐

  1. 02 getsockopt

    #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int getsockopt(int sockfd ...

  2. linux shell 命令笔记

    标准输入.标准输出.标准错误 File descriptors are integers associated with an opened file or data stream. File des ...

  3. 扩展微信小程序 Page 构造函数,修改生命周期函数

    不BB,直接正题 一. 将公共方法绑定到Page上 单个绑定 const oldPage = Page Page = function(app) { // 注意公共函数的名字不要重复,否则覆盖 app ...

  4. 借用的对vue-cli配置对解析

  5. A1046

    n个节点围成一个环,每个节点之间的距离已知.输入n并给出n个节点的距离,输入m组节点编号(两个),求这两个节点编号间的最短距离. 1 建立dis[]数组,记录V1点到每一个点的顺时针距离,sum计算环 ...

  6. Java的基本使用

    1.如何运行一个Java源码 打开文本编辑器,输入以下代码: public class Hello { public static void main(String[] args) { System. ...

  7. CityMaker SDK与三维GIS城市

    https://wenku.baidu.com/view/abc2a32f01f69e3142329426.html https://blog.csdn.net/weixin_38476447/art ...

  8. IDEA集成java编程规范插件

    第一种:如图所示搜索 Alibaba Java Coding Guidelines(阿里巴巴) 安装完成后,重启idea,点击tools>阿里巴巴编程>编程规约扫描 即可

  9. 利用python进行数据分析--pandas入门1

    随书练习,第五章  pandas入门1 # coding: utf-8 # In[1]: from pandas import Series, DataFrame # In[2]: import pa ...

  10. onload in JavaScript

    https://www.w3schools.com/tags/ev_onload.asp Example Execute a JavaScript immediately after a page h ...