上回我们讲到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. 关于C语言编译器Dev c++的调试

    大家应该都安装了C语言的编译软件,不过我个人认为Dev C++比VC6.0好用,所以只是说明DEv C++软件的调试方法 如果英文不好的,可以先汉化,再调试. 汉化:工具-----环境选项------ ...

  2. redhat6.5修改yum为163源

    把需要的安装包和配置文件打包,将命令整合到sh文件中,下载后解压运行yun_config.sh 即可 下载链接

  3. Jquery仿彩票更换数字动画效果

    <script type="text/javascript" src="jquery-1.11.3.min.js"></script> ...

  4. 【LeetCode】Add Digits

    Add Digits Given a non-negative integer num, repeatedly add all its digits until the result has only ...

  5. UVA 1151二进制枚举子集 + 最小生成树

    题意:平面上有n个点(1<=N<=1000),你的任务是让所有n个点连通,为此, 你可以新建一些边,费用等于两个端点的欧几里得距离的平方.另外还有q(0<=q<=8)个套餐(数 ...

  6. Android 学习第13课,android 实现发送短信的功能

    1. 界面布局 界面代码: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" ...

  7. Unity 摄像机组件

    今天看一下unity3d里面的摄像机是怎么调用和操作的. 打开unity3d新建一个工程.在我们打开工程的时候unity3d会主动添加一个Main Camera,在Hierartchy视图中.点击Ma ...

  8. The Swift Programming Language 中文翻译版(个人翻新随时跟新)

    The Swift Programming Language --lkvt 本人在2014年6月3日(北京时间)凌晨起来通过网络观看2014年WWDC 苹果公司的发布会有iOS8以及OS X 10.1 ...

  9. yii accessRules用法

    访问控制过滤器(Access Control Filter)访问控制过滤器是检查当前用户是否能执行访问的controller action的初步授权模式. 这种授权模式基于用户名,客户IP地址和访问类 ...

  10. Android之ListView&Json加载网络数据

    使用到的主要内容: 1.Json 解析网络数据 2.异步任务加载图片和数据 3.ListView 的内存空间优化(ConvertView)和运行时间优化(ViewHolder) 4.ListView ...