MyBatis原理分析之四:一次SQL查询的源码分析
上回我们讲到Mybatis加载相关的配置文件进行初始化,这回我们讲一下一次SQL查询怎么进行的。
准备工作
Mybatis完成一次SQL查询需要使用的代码如下:
- ) {
- );
- ) {
- throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
- } else {
- return null;
- }
- }
我们再看看selectList方法(实际上是调用该类的另一个selectList方法来实现的):
- public List selectList(String statement, Object parameter) {
- return selectList(statement, parameter, RowBounds.DEFAULT);
- }
- public List selectList(String statement, Object parameter, RowBounds rowBounds) {
- try {
- MappedStatement ms = configuration.getMappedStatement(statement);
- return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
- } catch (Exception e) {
- throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
- } finally {
- ErrorContext.instance().reset();
- }
- }
第二个selectList的执行步骤如下:
(1)根据SQL的ID到配置信息中找对应的MappedStatement,在之前配置被加载初始化的时候我们看到了系统会把配置文件中的SQL块解析并放到一个MappedStatement里面,并将MappedStatement对象放到一个Map里面进行存放,Map的key值是该SQL块的ID。
(2)调用执行器的query方法,传入MappedStatement对象、SQL参数对象、范围对象(此处为空)和结果处理方式。
好了,目前只剩下一个疑问,那就是执行器到底怎么执行SQL的呢?
上面我们知道了,默认情况下是采用SimpleExecutor执行的,我们看看这个类的doQuery方法:
- public List doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
- Statement stmt = null;
- try {
- Configuration configuration = ms.getConfiguration();
- StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, rowBounds, resultHandler);
- stmt = prepareStatement(handler);
- return handler.query(stmt, resultHandler);
- } finally {
- closeStatement(stmt);
- }
- }
doQuery方法的内部执行步骤:
(1) 获取配置信息对象。
(2)通过配置对象获取一个新的StatementHandler,该类主要用来处理一次SQL操作。
(3)预处理StatementHandler对象,得到Statement对象。
(4)传入Statement和结果处理对象,通过StatementHandler的query方法来执行SQL,并对执行结果进行处理。
我们看一下newStatementHandler到底做了什么?
- public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) {
- StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler);
- statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
- return statementHandler;
- }
上面代码的执行步骤:
(1)根据相关的参数获取对应的StatementHandler对象。
(2)为StatementHandler对象绑定拦截器插件。
RoutingStatementHandler类的构造方法RoutingStatementHandler如下:
- public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) {
- switch (ms.getStatementType()) {
- case STATEMENT:
- delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler);
- break;
- case PREPARED:
- delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler);
- break;
- case CALLABLE:
- delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler);
- break;
- default:
- throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
- }
- }
根据 MappedStatement对象的StatementType来创建不同的StatementHandler,这个跟前面执行器的方式类似。StatementType有STATEMENT、PREPARED和CALLABLE三种类型,跟JDBC里面的Statement类型一一对应。
我们看一下prepareStatement方法具体内容:
- private Statement prepareStatement(StatementHandler handler) throws SQLException {
- Statement stmt;
- Connection connection = transaction.getConnection();
- //从连接中获取Statement对象
- stmt = handler.prepare(connection);
- //处理预编译的传入参数
- handler.parameterize(stmt);
- return stmt;
- }
MyBatis原理分析之四:一次SQL查询的源码分析的更多相关文章
- STL 源码分析《2》----nth_element() 使用与源码分析
Select 问题: 在一个无序的数组中 找到第 n 大的元素. 思路 1: 排序,O(NlgN) 思路 2: 利用快排的 RandomizedPartition(), 平均复杂度是 O(N) 思路 ...
- Netty源码分析 (三)----- 服务端启动源码分析
本文接着前两篇文章来讲,主要讲服务端类剩下的部分,我们还是来先看看服务端的代码 /** * Created by chenhao on 2019/9/4. */ public final class ...
- HashMap源码分析(史上最详细的源码分析)
HashMap简介 HashMap是开发中使用频率最高的用于映射(键值对 key value)处理的数据结构,我们经常把hashMap数据结构叫做散列链表: ObjectI entry<Key, ...
- Mybatis Mapper接口是如何找到实现类的-源码分析
KeyWords: Mybatis 原理,源码,Mybatis Mapper 接口实现类,代理模式,动态代理,Java动态代理,Proxy.newProxyInstance,Mapper 映射,Map ...
- Guava cacha 机制及源码分析
1.ehcahce 什么时候用比较好:2.问题:当有个消息的key不在guava里面的话,如果大量的消息过来,会同时请求数据库吗?还是只有一个请求数据库,其他的等待第一个把数据从DB加载到Guava中 ...
- Spring源码分析之Bean的创建过程详解
前文传送门: Spring源码分析之预启动流程 Spring源码分析之BeanFactory体系结构 Spring源码分析之BeanFactoryPostProcessor调用过程详解 本文内容: 在 ...
- jQuery源码分析系列
声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://git ...
- jquery2源码分析系列
学习jquery的源码对于提高前端的能力很有帮助,下面的系列是我在网上看到的对jquery2的源码的分析.等有时间了好好研究下.我们知道jquery2开始就不支持IE6-8了,从jquery2的源码中 ...
- [转]jQuery源码分析系列
文章转自:jQuery源码分析系列-Aaron 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAaro ...
随机推荐
- Why jsp?
Before the JSP come into the world . The CGI and servlet took the responsibility of generating dynam ...
- MySQL设置字符集为UTF8(Windows版)
Windows版MySQL设置字符集全部为utf8的方式 MySQL安装目录下的my.ini文件 [client]节点 default-character-set=utf8 (增加) [mysq ...
- [转载 ]POJ 1273 最大流模板
转载 百度文库花了5分下的 不过确实是自己需要的东西经典的最大流题POJ1273 ——其他练习题 POJ3436 . 题意描述: 现在有m个池塘(从1到m开始编号,1为源点,m为汇点),及n条水渠,给 ...
- 黑马程序员:Java编程_7K面试题之交通灯管理系统
=========== ASP.Net+Android+IOS开发..Net培训.期待与您交流!=========== 模拟实现十字路口的交通灯管理系统逻辑,具体需求如下: 异步随机生成按照各个路线行 ...
- Linux系统启动错误 contains a file system with errors, check forced解决方法
/dev/sda1 contains a file system with errors, check forced./dev/sda1: Inodes that were part of a cor ...
- android-文件存储的使用
Android提供了5种方式存储数据: 1.使用SharedPreferences存储数据: 2.文件存储数据: 3.SQLite数据库存储数据: 4.使用ContentProvider存储数据: 5 ...
- 十分钟了解分布式计算:Google Dataflow
介绍 Google Cloud Dataflow是一种构建.管理和优化复杂数据处理流水线的方法,集成了许多内部技术,如用于数据高效并行化处理的Flume和具有良好容错机制流处理的MillWheel.D ...
- VTK的学习资源
本文介绍从哪儿开始学习VTK(Visualization Toolkit的简称),如何在网上找寻VTK的学习资源. 首先,可以到维基百科或者百度百科上查看VTK条目,了解VTK是什么. http:// ...
- 集合框架(JCF/Java Collection Framework)
集合的特点:1.数据的类型可以不同2.集合长度可变3.空间不固定集合也是对象,用于检索,存储以及传输对象集合框架的组成Collection接口和Map接口 Collection是Set接口和List接 ...
- 我关注的一些关于前端的文章(copy)
本文的核心是侧重于HTML/CSS的框架,JS框架或以JS为核心的框架不讨论(比如YUI):多屏已是既定事实,虽然不是所有开发都要考虑自适应,但有自适应功能至少说明了这框架短期内不会被淘汰,所以不带自 ...