上回我们讲到Mybatis加载相关的配置文件进行初始化,这回我们讲一下一次SQL查询怎么进行的。

准备工作

Mybatis完成一次SQL查询需要使用的代码如下:

  1. ) {
  2. );
  3. ) {
  4. throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
  5. } else {
  6. return null;
  7. }
  8. }

我们再看看selectList方法(实际上是调用该类的另一个selectList方法来实现的):

  1. public List selectList(String statement, Object parameter) {
  2. return selectList(statement, parameter, RowBounds.DEFAULT);
  3. }
  4. public List selectList(String statement, Object parameter, RowBounds rowBounds) {
  5. try {
  6. MappedStatement ms = configuration.getMappedStatement(statement);
  7. return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
  8. } catch (Exception e) {
  9. throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
  10. } finally {
  11. ErrorContext.instance().reset();
  12. }
  13. }

第二个selectList的执行步骤如下:

(1)根据SQL的ID到配置信息中找对应的MappedStatement,在之前配置被加载初始化的时候我们看到了系统会把配置文件中的SQL块解析并放到一个MappedStatement里面,并将MappedStatement对象放到一个Map里面进行存放,Map的key值是该SQL块的ID。

(2)调用执行器的query方法,传入MappedStatement对象、SQL参数对象、范围对象(此处为空)和结果处理方式。

好了,目前只剩下一个疑问,那就是执行器到底怎么执行SQL的呢?

上面我们知道了,默认情况下是采用SimpleExecutor执行的,我们看看这个类的doQuery方法:

  1. public List doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
  2. Statement stmt = null;
  3. try {
  4. Configuration configuration = ms.getConfiguration();
  5. StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, rowBounds, resultHandler);
  6. stmt = prepareStatement(handler);
  7. return handler.query(stmt, resultHandler);
  8. } finally {
  9. closeStatement(stmt);
  10. }
  11. }

doQuery方法的内部执行步骤:

(1) 获取配置信息对象。

(2)通过配置对象获取一个新的StatementHandler,该类主要用来处理一次SQL操作。

(3)预处理StatementHandler对象,得到Statement对象。

(4)传入Statement和结果处理对象,通过StatementHandler的query方法来执行SQL,并对执行结果进行处理。

我们看一下newStatementHandler到底做了什么?

  1. public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) {
  2. StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler);
  3. statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
  4. return statementHandler;
  5. }

上面代码的执行步骤:

(1)根据相关的参数获取对应的StatementHandler对象。

(2)为StatementHandler对象绑定拦截器插件。

RoutingStatementHandler类的构造方法RoutingStatementHandler如下:

  1. public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) {
  2. switch (ms.getStatementType()) {
  3. case STATEMENT:
  4. delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler);
  5. break;
  6. case PREPARED:
  7. delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler);
  8. break;
  9. case CALLABLE:
  10. delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler);
  11. break;
  12. default:
  13. throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
  14. }
  15. }

根据 MappedStatement对象的StatementType来创建不同的StatementHandler,这个跟前面执行器的方式类似。StatementType有STATEMENT、PREPARED和CALLABLE三种类型,跟JDBC里面的Statement类型一一对应。

我们看一下prepareStatement方法具体内容:

  1. private Statement prepareStatement(StatementHandler handler) throws SQLException {
  2. Statement stmt;
  3. Connection connection = transaction.getConnection();
  4. //从连接中获取Statement对象
  5. stmt = handler.prepare(connection);
  6. //处理预编译的传入参数
  7. handler.parameterize(stmt);
  8. return stmt;
  9. }

MyBatis原理分析之四:一次SQL查询的源码分析的更多相关文章

  1. STL 源码分析《2》----nth_element() 使用与源码分析

    Select 问题: 在一个无序的数组中 找到第 n 大的元素. 思路 1: 排序,O(NlgN) 思路 2: 利用快排的 RandomizedPartition(), 平均复杂度是 O(N) 思路 ...

  2. Netty源码分析 (三)----- 服务端启动源码分析

    本文接着前两篇文章来讲,主要讲服务端类剩下的部分,我们还是来先看看服务端的代码 /** * Created by chenhao on 2019/9/4. */ public final class ...

  3. HashMap源码分析(史上最详细的源码分析)

    HashMap简介 HashMap是开发中使用频率最高的用于映射(键值对 key value)处理的数据结构,我们经常把hashMap数据结构叫做散列链表: ObjectI entry<Key, ...

  4. Mybatis Mapper接口是如何找到实现类的-源码分析

    KeyWords: Mybatis 原理,源码,Mybatis Mapper 接口实现类,代理模式,动态代理,Java动态代理,Proxy.newProxyInstance,Mapper 映射,Map ...

  5. Guava cacha 机制及源码分析

    1.ehcahce 什么时候用比较好:2.问题:当有个消息的key不在guava里面的话,如果大量的消息过来,会同时请求数据库吗?还是只有一个请求数据库,其他的等待第一个把数据从DB加载到Guava中 ...

  6. Spring源码分析之Bean的创建过程详解

    前文传送门: Spring源码分析之预启动流程 Spring源码分析之BeanFactory体系结构 Spring源码分析之BeanFactoryPostProcessor调用过程详解 本文内容: 在 ...

  7. jQuery源码分析系列

    声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://git ...

  8. jquery2源码分析系列

    学习jquery的源码对于提高前端的能力很有帮助,下面的系列是我在网上看到的对jquery2的源码的分析.等有时间了好好研究下.我们知道jquery2开始就不支持IE6-8了,从jquery2的源码中 ...

  9. [转]jQuery源码分析系列

    文章转自:jQuery源码分析系列-Aaron 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAaro ...

随机推荐

  1. pyqt5

    使用python爬虫需要使用webkit执行javascript,查找资料可使用pyqt5,在此记录下安装步骤 windows 安装pyqt5 操作webkit 可用版本 1. 下载python 3. ...

  2. .net 下判断中英文字符串长度

    System.Text.Encoding.Default.GetBytes(str).Length

  3. HDU 5384 AC自动机

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=5384 题意:给n个母串,给m个匹配串,求每个母串依次和匹配串匹配,能得到的数目和. 分析:之前并不知道AC ...

  4. ThinkPHP 自动验证相关注意

    1.假如加入了表单令牌的话,表单的各种名与对应Model字段一致,不然报坑爹的令牌错误. 2.假如加入了表单令牌的话,Create只能采用默认的POST数据创建数据对象,不然又是坑爹的令牌错误. 3. ...

  5. winform在设置控件enabled=false后,无法更改控件字体颜色的问题

    项目界面设计的时候,发现在设置button的enabled=false后,原本设计的字体颜色跟预设的不一样,查了一些资料后,在网上看到这样一段代码: [System.Runtime.InteropSe ...

  6. [GodLove]Wine93 Tarining Round #8

    比赛链接: http://vjudge.net/contest/view.action?cid=47644#overview 比赛来源: 2012 ACM/ICPC Asia Regional Tia ...

  7. Python——Day3知识点——文件操作

    一.打开文件 文件句柄 = open('文件路径', '模式') 打开文件时,需要指定文件路径和以何等方式打开文件,打开后,即可获取该文件句柄,日后通过此文件句柄对该文件操作. 打开文件的模式有: r ...

  8. js获取url的常用方法

    //设置或获取对象指定的文件名或路径. console.log(window.location.pathname) //设置或获取整个 URL 为字符串. console.log(window.loc ...

  9. 使用 AdaBoost 元算法提高分类器性能

    前言 有人认为 AdaBoost 是最好的监督学习的方式. 某种程度上因为它是元算法,也就是说它会是几种分类器的组合.这就好比对于一个问题能够咨询多个 "专家" 的意见了. 组合的 ...

  10. logcat 基本使用

    adb logcat -c    //清空以前的日志 adb logcat -v time >  d:/sss.log       //将当前日志输出到d盘的sss.log中  sss.log不 ...