一切的执行从MapperProxy开始,MapperProxy是MapperProxyFactory使用SqlSession创建出来的。所以MapperProxy中包含SqlSession。

  可以看到MapperProxy调用invoke方法,进而调用MapperMethod的execute(),这些MapperMethod就是和你要执行的命令相关,比如执行select语句,则会通过SqlSession的select()方法,最终调用到Executor的query方法。Executor会再协调另外三个核心组件。

  • MapperProxyFactory用来创建MapperProxy,这个factory其实主要就是完成了InvokeHandler的bindTarget的功能。而MapperProxy只需要完成invoke方法的功能。
  • MapperProxy包含SqlSession
  • SqlSesion包含四大组件Executor,StatementHandler,ParameterHandler,ResultHandler。还包含Configuration
  • Configuration可以创建四大组件,同时Configuration还包含InterceptorChain,通过调用interceptorChain的pluginAll()方法,完成针对四大组件的插件的动态代理链的创建。

MapperProxy:

  • 因为Mapper接口不能直接被实例化,Mybatis利用JDK动态代理,创建MapperProxy间接实例化Mapper对象。
  • MapperProxy还可以缓存MapperMethod对象

MapperMethod:

  • 负责解析Mapper接口的方法,并封装成MapperMethod对象
  • 将Sql命令的执行路由到恰当的SqlSesison方法上
 1 public class MapperMethod {
2
3 // 保存了Sql命令的类型和键id
4 private final SqlCommand command;
5 // 保存了Mapper接口方法的解析信息
6 private final MethodSignature method;
7
8 public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
9 this.command = new SqlCommand(config, mapperInterface, method);
10 this.method = new MethodSignature(config, method);
11 }
12
13 // 根据解析结果,路由到恰当的SqlSession方法上
14 public Object execute(SqlSession sqlSession, Object[] args) {
15 Object result;
16 if (SqlCommandType.INSERT == command.getType()) {
17 Object param = method.convertArgsToSqlCommandParam(args);
18 result = rowCountResult(sqlSession.insert(command.getName(), param));
19 } else if (SqlCommandType.UPDATE == command.getType()) {
20 Object param = method.convertArgsToSqlCommandParam(args);
21 result = rowCountResult(sqlSession.update(command.getName(), param));
22 } else if (SqlCommandType.DELETE == command.getType()) {
23 Object param = method.convertArgsToSqlCommandParam(args);
24 result = rowCountResult(sqlSession.delete(command.getName(), param));
25 } else if (SqlCommandType.SELECT == command.getType()) {
26 if (method.returnsVoid() && method.hasResultHandler()) {
27 executeWithResultHandler(sqlSession, args);
28 result = null;
29 } else if (method.returnsMany()) {
30 result = executeForMany(sqlSession, args);
31 } else if (method.returnsMap()) {
32 result = executeForMap(sqlSession, args);
33 } else {
34 Object param = method.convertArgsToSqlCommandParam(args);
35 result = sqlSession.selectOne(command.getName(), param);
36 }
37 } else if (SqlCommandType.FLUSH == command.getType()) {
38 result = sqlSession.flushStatements();
39 } else {
40 throw new BindingException("Unknown execution method for: " + command.getName());
41 }
42 if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
43 throw new BindingException("Mapper method '" + command.getName()
44 + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
45 }
46 return result;
47 }
48 // ...

插件的构建:

  谈原理首先要知道StatementHandler,ParameterHandler,Result Handler都是代理,他们是Configuration创建,在创建过程中会调用interceptorChain.pluginAll()方法,为四大组件组装插件(再底层是通过Plugin.wrap(target,XX, new Plugin( interceptor))来来创建的)。

插件链是何时构建的:

  在执行SqlSession的query或者update方法时,SqlSession会通过Configuration创建Executor代理,在创建过程中就调用interceptor的pluginAll方法组装插件。然后executor在调用doQuery()方法的时候,也会调用Configuration的newStatementHandler方法创建StatemenHandler(和上面描述的一样,这个handler就是个代理,也是通过interceptorChain的pluginAll方法构建插件)

插件如何执行:

  以statementhandler的prepare方法的插件为例,正如前面所说,statementhandler是一个proxy,执行他的prepare方法,将调用invokeHandler的invoke方法,而invokeHandler就是Plugin.wrap(target, xxx, new Plugin(interceptor))中的第三个参数,所以很自然invokeHanlder的invoke的方法最终就会调用interceptor对象的intercept方法。

Mybatis执行SQL的完整过程及四大组件介绍的更多相关文章

  1. 一个PHP的SQL注入完整过程

    本篇文章介绍的内容是一个PHP的SQL注入完整过程,现在分享给大家,有需要的朋友可以参考一下 希望帮助到大家,很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里 ...

  2. Mybatis执行sql(insert、update、delete)返回值问题

    数据库:Mysql 在使用mybatis的过程中对执行sql的返回值产生疑问,顺手记录一下. 结论: insert:   插入n条记录,返回影响行数n.(n>=1,n为0时实际为插入失败) up ...

  3. 在mybatis执行SQL语句之前进行拦击处理

    转载自:http://blog.csdn.net/hfmbook/article/details/41985853 比较适用于在分页时候进行拦截.对分页的SQL语句通过封装处理,处理成不同的分页sql ...

  4. log4j打印mybatis执行sql,将占位符换成真实的参数输出

    背景: 在我日常码代码的时候,由于对mybatis的动态sql,比较依赖,并且有时候需求复杂,导致sql较长,而且参数众多,当出现问题是,需要将sql,放到navicat里面去执行查看结果,但是对于复 ...

  5. oracle-SQL语句执行原理和完整过程详解

    SQL语句执行过程详解 一条sql,plsql的执行到底是怎样执行的呢? 一.SQL语句执行原理 第一步:客户端吧语句发个服务端执行 当我们在客户端执行select语句时,客户端会把这条SQL语句发送 ...

  6. Mybatis执行SQL的流程

    前篇:Mybatis初始化过程 SqlSession : SqlSession是一个接口,它有两个实现类:DefaultSqlSession (默认)和 SqlSessionManager (弃用,不 ...

  7. mybatis整合spring的完整过程

    1.1 整合思路 1.SqlSessionFactory对象应该放到spring容器中作为单例存在. 2.传统dao的开发方式中,应该从spring容器中获得sqlsession对象. 3.Mappe ...

  8. Oracle执行SQL语句的过程

    转载至:http://blog.csdn.net/aqszhuaihuai/article/details/7024551 当我们提交一条sql语句时,Oracle会做哪些操作呢? Oracle会为每 ...

  9. 使用Mybatis执行sql脚本

    pom.xml <?xml version="1.0" encoding="UTF-8"?> <project xmlns="htt ...

随机推荐

  1. Springer editorial manager上传latex文件

    Springer的投稿系统editorial manager在初次投稿时只需要上传pdf文件,修改后要求上传Latex源文件.上传过程遇到好多问题,花了快两天才搞定,整理如下: 1. 主要上传的文件包 ...

  2. Python练习题 032:Project Euler 004:最大的回文积

    本题来自 Project Euler 第4题:https://projecteuler.net/problem=4 # Project Euler: Problem 4: Largest palind ...

  3. Blend学习之Loading加载动画

    介绍: Blend for visual studio 与 visual studio 是有区别的 两者虽然是IDEA 但是专注的方向是不同的,前者是专注UI后者专注业务逻辑,当然你要用blend f ...

  4. Python3——字典

    Python 字典(Dictionary) 字典是另一种可变容器模型,且可存储任意类型对象. 字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割,整个字典包括在 ...

  5. CRUD,分页,排序,搜索与AngularJS在MVC

    下载source - 53.1 MB 介绍 在选择最新的技术时,有几个因素会起作用,包括这些技术将如何与我们的项目集成.这篇文章解决了开始使用AngularJS和MVC的乞丐的问题.这篇文章告诉使用语 ...

  6. JVM 第四篇:可视化 JVM 故障处理工具

    本文内容过于硬核,建议有 Java 相关经验人士阅读. 1. 可视化工具 在 JDK 中为我们提供了大量的 JVM 故障处理工具,都在 JDK 的 bin 目录下: 这其中除了大量的命令行工具以外,还 ...

  7. xxe 新手学习记录

    在做某题时遇到了xxe漏洞,学习+记录 这里因为环境暂时关了,现在复现不了,所以在网络上又找到了一些xxe题目环境 这里有 PikaChu靶场里的xxe环境,这个环境可以在BUUCTF里开,但是这里我 ...

  8. 关于keytool和jarsigner工具签名的使用小结

    在我们日常Android应用开发中,我们都要对我们开发的apk做签名处理,或者加固,增强我们apk的安全性,防止被逆向反编译,在apk签名这块,我们一般采用JDK自动工具来签名,下面就对相关工具做个简 ...

  9. 记录小坑-tp5 使用模型select查询

    场景: 使用模型去select查询后进行业务处理 再进行 saveAll 提示缺少更新条件 坑点:此时取出的数据结构是 query对象 { array:[ xxxx => xxx ] }: sa ...

  10. 同一台电脑同时使用gitHub和gitLab

    工作中我们有时可能会在同一台电脑上使用多个git账号,例如:公司的gitLab账号,个人的gitHub账号.怎样才能在使用gitlab与github时,切换成对应的账号,并且免密?这时我们需要使用ss ...