前三篇Mybatis的原理解析可以点击链接查看:

Mybatis原理解析(一)解析全局xml配置文件生成SqlSessionFactory过程

Mybatis原理解析(二)SqlSession的创建过程

Mybatis原理解析(三)--getMapper动态获取接口实现类

这一篇主要讲的是在前三篇的基础上Mybatis的查询流程(与增删改同理),也是Mybatis中最为核心的知识,话不多说,debug为敬。

我们在第三篇中说了我们得到的Mapper接口对象其实是一个代理实现类,被代理的是MapperProxy对象,而MapperProxy对象并没有实现我们的Mapper接口,所以说当我们调用代理类的接口方法时,invoke方法会给出一个条件判断是否是Object类的方法(如果这里没有这个判断那么程序会报错,详情可以看第三篇的解释),很明显我们调用的是接口的方法,不是Object的方法,所以我们的程序直接来到cachedMapperMethod方法,深入这个方法

 在这里其实就是做了个优化,通过一个map容器去缓存我们的MapperMethed,key为调用的接口方法Method,value为MapperMethod。而这个MapperMethod里面主要有两个属性:

其中一个SqlCommand对象,那么我们来看下这个SqlCommand里面有什么,来到它的构造函数

首先它是MapperMethod的一个内部类,里面有两个属性分别是name,type,那么我这里就直接给大家说了这个两个属性的作用了,name属性根据传过来的interface以及method得到我们调用的方法的全路径名称去Configuration里面去拿到对应的MappedStatement,然后再把得到的MappedStatement对象的id赋值给name,而type同理,也是MappedStatement的sqlCommandType赋值得到的。而另外的一个MethodSignature也是MapperMethod的内部类,作用就是判断调用的接口方法的返回是什么类型,这里就不多讲述了。

上面说的这两个类,其实是在为下面做铺垫,我们点击下一步,来到mapperMethod.execute方法,继续深入。

可以看出这里首先就是通过MapperMethod里面的SqlCommand的type去判断方法类型,由于我们这里是一个查询方法,所以来到了SELECT分支中

在SELECT分支中,又去判断方法的返回值,根据方法的返回值不同就去到不同的if分支,而明显这里能有条件去判断就是我们上面说的MethodSignature的功劳了。接下来来到了sqlSession.selectOne方法,传入了方法的全路径名称以及调用的接口方法参数,继续深入。

深入selectList方法。

继续深入。

 可以看到这里根据了前面sqlCommond的name值去Configuration对象里面得到对应的MappedStatement对象,然后调用executor.query方法,注意这里有一个wrapCollection方法,从名字可以看出应该是给我们的参数对象进行包装,这里不多讲述。然后继续深入query方法。

通过传进来的MappedStatement的getBoundSql方法可以得到BoundSql对象,该对象里面包含有了我们原始的sql语句。而CacheKey是给我们的二级缓存使用的一个key值,继续深入下面的query方法。

 这里调用到了CachingExecutor的query方法,因为我们这里是默认配置了二级缓存的,所以我们真正执行的Executor会被CachingExcutor包装了,这里我们的第二篇里面有讲到了,不再详细讲述。然后如果我们二级缓存中没有数据的话,就要调用打我们真正的executor了。深入delegate.query方法。

这里和二级缓存类似,是先从本地缓存中取,即一级缓存,所以这里我们可以知道Mybatis里面是数据来源顺序是先二级缓存,再一级缓存,最后数据库中取。我们深入到queryFromDataBase这个方法中。

深入doQuery方法

 此时来到了SimpleExecutor的doQuery方法,看到先从传入的MappedStatement对象拿到Configuration对象,然后调用了configuration的newStatementHandler方法,该方法返回了一个StatementHandler对象,深入这个方法。

可以看到里面先是通过子类创建了一个RoutingStatemnetHandler对象,这个RoutingStatemnetHandler对象是什么尼?我们进去它的构造方法看看。

在它的属性中,有一个StatementHandler的属性对象,其实这个属性对象才是这个类的方法的真正执行对象,即这个RoutingStatementHandler其实就是做了一层包装而已,而创建这个对象是根据我们在配置文件中设置的statementType来确定的,默认是创建一个预编译的PrepareStatementHandler。

然后看上面红框的这句代码interceptorChain.pluginAll(statementHandler),很熟悉的一句代码,其实在我们初始化Executor的时候也出现过这句代码,在后面的代码我们也会看见这一句代码,这是与Mybatis的插件机制相关的。那么这个StatementHandler对象是什么尼?我们先执行看下面的代码。

执行完这个newStatementHandler方法之后,来到了下面的prepareStatement方法,深入这个方法。

可以看出其实我们的StatementHandler对象就是用来获取Statement对象的,而这个Statement对象就是我们在学习JDBC编程的时候jdk里面的Statement对象,所以Mybatis对数据库的操作其实也是封装了JDBC的。下面我们来看下StatementHandler是怎么获取Statement的,深入handler.prepare

可以看到里面是调用了prepareStatement的prepare方法,深入这个方法。

 可以看到这里显示从boundSql里面拿到sql语句,然后调用connection.prepareStatement方法把sql传入去,这样就得到了Statement对象了。

之后就来到了handler.parameterize(stmt),然后我们深入进去看看。

里面调用了parameterHandler的setParameters方法,而这个parameterHandler对象是什么?我们回到之前初始化PreparedStatementHandler那里。

PreparedStatementHandler里面并没有这个parameterHandler对象,而PreparedStatementHandler是继承于BaseStatementHandler,所以初始化parameterHandler对象应该是在其父类BaseStatementHandler的构造方法中。

来到BaseStatementHandler的构造方法,深入configuration.newParameterHandler方法。

可以看出newParameterHandler和newResultSetHandler都有调用到Mybatis插件机制。而目前我们所知的能被Mybatis插件拦截的有Executor,StatementHandler,ParameterHandler,ResultSetHandler这个四个对象,其实能被Mybatis插件拦截的也就这四大对象了在Mybatis中,我们习惯称为这是Mybatis四大组件。

Mybatis原理解析(四)--查询流程相关推荐

  1. 深入剖析 mybatis 原理(四)插件的原理和应用

    < 一生所爱> 从前现在过去了再不来 红红落叶长埋尘土内 开始终结总是没变改 天边的你飘泊白云外 苦海翻起爱恨 在世间难逃避命运 相亲竟不可接近 或我应该相信是缘份 情人别后永远再不来(消 ...

  2. MyBatis原理解析

    参考自: MyBatis原理分析(通俗易懂)_Coder Wang-CSDN博客_mybatis原理 从源码一层一层进行分析,写得清晰易懂.我再这里就不赘述了,就写一下自己的大白话总结吧. Mybat ...

  3. java解析sql语句简书,Mybatis原理解析(一)--java.sql数据库操作的基本实现方式

    在研究Mybatis原理之前,先看一下java中是如何实现一次对数据库的访问的: public void testSql() { Connection connection = null; State ...

  4. ES5.6.4源码解析--聚合查询流程

    es的聚合查询会涉及到很多概念,比如fielddata,DocValue,也会引出很多问题,比如聚合查询导致的内存溢出.在没有真正了解聚合查询的情况下,我们往往对这些概念,问题都是云山雾绕的.本文我们 ...

  5. Java多线程系列 JUC线程池05 线程池原理解析(四)

    转载 http://www.cnblogs.com/skywang12345/p/3544116.html  https://blog.csdn.net/programmer_at/article/d ...

  6. Pix2Pix原理解析以及代码流程

    文章目录 1.网络搭建 2.反向传播过程 3.PatchGAN 4.与CGAN的不同之处 1.网络搭建 class UnetGenerator(nn.Module):""" ...

  7. 微服务精通之Hystrix原理解析

    前言 经过微服务精通之Ribbon原理解析的学习,我们了解到了服务消费者获取服务提供者实例的过程,在这之后,服务消费者会调用服务提供者的接口.但是在调用接口的过程中,我们经常会遇见服务之间的延迟和通信 ...

  8. Vue 原理解析(五)之 虚拟Dom 到真实Dom的转换过程

    上一篇 vue 原理解析(四): 虚拟Dom 是怎么生成的 再有一颗树形结构的Javascript对象后, 我们需要做的就是讲这棵树跟真实Dom树形成映射关系.我们先回顾之前的mountComponn ...

  9. MyBatis原理分析之获取SqlSession

    流程原理分析系列: MyBatis原理分析之获取SqlSessionFactory MyBatis原理分析之获取SqlSession MyBatis原理分析之获取Mapper接口的代理对象 MyBat ...

  10. 微服务精通之Feign原理解析

    前言 经过微服务精通之Ribbon原理解析的学习,我们了解到了服务消费者获取服务提供者实例的过程,都是通过RestTemplate来实现的,而且,都是模板化操作.那spring cloud是否有哪个组 ...

最新文章

  1. Python使用numpy包编写自定义函数计算均方误差(MSE、mean squared error)、评估回归模型和时间序列模型、解读MSE评估指标
  2. adb 测试工作中的总结
  3. 小程序云开发搜索功能的实现正则_几行代码实现小程序云开发提现功能
  4. 多线程总结之旅(12):跨线程调用控件的几种方式
  5. Java与本机代理–他们所做的强大功能
  6. Music List
  7. 【数据结构算法】快排/归并/堆排序 c++
  8. Python安装dlib包
  9. 腾讯回应 PC 微信扫描浏览器 cookies;约会网站 228 万用户数据泄露;Java 1.0 发布 25周年 | 极客头条...
  10. 博文视点大讲堂第29期——2天玩转单反相机
  11. 【招】阿里云技术战略高级专家
  12. 史上最傻java代码记录
  13. 关于DSP28335CCS6编译时出现error #10099-D: program will not fit into available memory.
  14. 蛋白质生物学概述(一)
  15. linux进入欢迎界面一直重启,Linux无限重启怎么办
  16. 高清液晶触控一体机整合传播,优势明显
  17. 小白从0学习推荐系统 ---01 推荐系统简介
  18. 认证学习4 - Bearer认证(Token认证)讲解、代码实现、演示
  19. UG 二次开发中文帮助文档,UFun在线帮助文档, NX API 中文帮助文档
  20. 决策树算法原理及应用(详细版)

热门文章

  1. 价值连城 ImageNet图像分类大神 Andrej Karpathy的采访 给AI 深度学习从业者的建议
  2. B-S期权定价模型 Black Scholdz
  3. git branch查看/删除分支
  4. 609. 在系统中查找重复文件
  5. 240.搜索二维矩阵II
  6. 赢在微点答案专区英语_自考英语二太难?看了墨盒的单词本,保你信心满满去考试!...
  7. 现代通信原理A.5:数字基带传输系统误码性能仿真
  8. SSM(Spring+SpringMVC+MyBatis):图书管理系统附有GIF动图,博主可免费答疑
  9. 医学相关excel表格计算机作业,求计算机作业电子表格演示文稿。
  10. mysql 更新删除数据,MYSQL数据的插入、删除、更新