上回我们讲到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. CxImage在VS2010下的配置

    http://blog.csdn.net/youzhuo/article/details/24601621 一.编译Cximage 1.在SourceForge上下载cximage702_full.7 ...

  2. react native 之 react-native-image-picke的详细使用图解

    最近需要在react native项目中集成相机和相册的功能,于是在网上找了一个好用的第三方插件:react-native-image-picke. 该插件可以同时给iOS和Android两个平台下使 ...

  3. Ruby on Rails搭建环境出现的问题及解决方案

    问题一:在win7系统64位环境下执行cmd命令:rails new testapp 之后,回报如下图错误:Gem:installer::ExtensionBuildError: ERROR:Fail ...

  4. Azure Media Service

    该视频来源于Build 2015, 视频比较老, 从演讲的角度看, 是个非常不错的演讲, 内容也很全面. Apr 27, 2015

  5. win32自绘按钮,使用GDI+(一)

    第一次写随笔,我本来想将win32窗口的标题栏设置成渐变色,像这样的效果 但发现找不到设置标题栏属性的api,SetWindowLong也只是增减窗口的固定的样式而已.所以想到一个思路,把标题栏去掉, ...

  6. 转载:Android横屏竖屏切换的问题

    一.禁止横竖屏转换 Android横竖屏切换在手机开发中比较常见,很多软件在开发过程中为了避免横竖屏切换时引发不必要的麻烦,通常禁止掉横竖屏的切换, 通过在AndroidManifest.xml中设置 ...

  7. devexpress xaf 开发中遇到的问题.

    devexpress xaf 开发中遇到的问题很多久了就忘记了.每天都把开发内容记录下来,方便大家,方便自己

  8. Pixel VS Point, FrameBuffer VS RenderBuffer

    // How iOS app MVC works View, Window, AppDelegate ViewController, RootViewController // On Pixel VS ...

  9. 浏览器 HTTP 协议缓存机制详解

    最近在准备优化日志请求时遇到了一些令人疑惑的问题,比如为什么响应头里出现了两个 cache control.为什么明明设置了 no cache 却还是发请求,为什么多次访问时有时请求里带了 etag, ...

  10. iOS复选框

    这种按钮iOS没有原生效果. 可以靠按钮的不同点击状态来实现这个效果. 代码如下: _workBtn = [UIButton buttonWithType:UIButtonTypeCustom]; [ ...