2019独角兽企业重金招聘Python工程师标准>>>

Mybatis中的Sql命令,在枚举类SqlCommandType中定义的。

public enum SqlCommandType {UNKNOWN, INSERT, UPDATE, DELETE, SELECT, FLUSH;
}

下面,我们以Mapper接口中的一个方法作为例子,看看Sql命令的执行完整流程。

public interface StudentMapper {List<Student> findAllStudents(Map<String, Object> map, RowBounds rowBounds, ResultSetHandler rh);
}

参数RowBounds和ResultSetHandler是可选参数,表示分页对象和自定义结果集处理器,一般不需要。

一个完整的Sql命令,其执行的完整流程图如下:

(Made In Edrawmax)

对于上面的流程图,如果看过前面的博文的话,大部分对象我们都比较熟悉了。一个图,就完整展示了其执行流程。

MapperProxy的功能:

1. 因为Mapper接口不能直接实例化,MapperProxy的作用,就是使用JDK动态代理功能,间接实例化Mapper的proxy对象。可参看系列博文的第二篇。

2. 缓存MapperMethod对象。

  private final Map<Method, MapperMethod> methodCache;@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if (Object.class.equals(method.getDeclaringClass())) {try {return method.invoke(this, args);} catch (Throwable t) {throw ExceptionUtil.unwrapThrowable(t);}}// 投鞭断流final MapperMethod mapperMethod = cachedMapperMethod(method);return mapperMethod.execute(sqlSession, args);}// 缓存MapperMethodprivate MapperMethod cachedMapperMethod(Method method) {MapperMethod mapperMethod = methodCache.get(method);if (mapperMethod == null) {mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());methodCache.put(method, mapperMethod);}return mapperMethod;}

MapperMethod的功能:

1. 解析Mapper接口的方法,并封装成MapperMethod对象。

2. 将Sql命令,正确路由到恰当的SqlSession的方法上。

public class MapperMethod {// 保存了Sql命令的类型和键idprivate final SqlCommand command;// 保存了Mapper接口方法的解析信息private final MethodSignature method;public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {this.command = new SqlCommand(config, mapperInterface, method);this.method = new MethodSignature(config, method);}// 根据解析结果,路由到恰当的SqlSession方法上public Object execute(SqlSession sqlSession, Object[] args) {Object result;if (SqlCommandType.INSERT == command.getType()) {Object param = method.convertArgsToSqlCommandParam(args);result = rowCountResult(sqlSession.insert(command.getName(), param));} else if (SqlCommandType.UPDATE == command.getType()) {Object param = method.convertArgsToSqlCommandParam(args);result = rowCountResult(sqlSession.update(command.getName(), param));} else if (SqlCommandType.DELETE == command.getType()) {Object param = method.convertArgsToSqlCommandParam(args);result = rowCountResult(sqlSession.delete(command.getName(), param));} else if (SqlCommandType.SELECT == command.getType()) {if (method.returnsVoid() && method.hasResultHandler()) {executeWithResultHandler(sqlSession, args);result = null;} else if (method.returnsMany()) {result = executeForMany(sqlSession, args);} else if (method.returnsMap()) {result = executeForMap(sqlSession, args);} else {Object param = method.convertArgsToSqlCommandParam(args);result = sqlSession.selectOne(command.getName(), param);}} else if (SqlCommandType.FLUSH == command.getType()) {result = sqlSession.flushStatements();} else {throw new BindingException("Unknown execution method for: " + command.getName());}if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {throw new BindingException("Mapper method '" + command.getName() + " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");}return result;}// ...

org.apache.ibatis.binding.MapperMethod.SqlCommand。

public static class SqlCommand {// full id, 通过它可以找到MappedStatementprivate final String name;private final SqlCommandType type;
// ...

org.apache.ibatis.binding.MapperMethod.MethodSignature。

  public static class MethodSignature {private final boolean returnsMany;private final boolean returnsMap;private final boolean returnsVoid;private final Class<?> returnType;private final String mapKey;private final Integer resultHandlerIndex;private final Integer rowBoundsIndex;private final SortedMap<Integer, String> params;private final boolean hasNamedParameters;public MethodSignature(Configuration configuration, Method method) {this.returnType = method.getReturnType();this.returnsVoid = void.class.equals(this.returnType);this.returnsMany = (configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray());this.mapKey = getMapKey(method);this.returnsMap = (this.mapKey != null);this.hasNamedParameters = hasNamedParams(method);// 分页参数this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class);// 自定义ResultHandlerthis.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class);this.params = Collections.unmodifiableSortedMap(getParams(method, this.hasNamedParameters));}

以上是对MapperMethod的补充说明。

本节的重点,是上面的那个Sql命令完整执行流程图。如果不是使用Mapper接口调用,而是直接调用SqlSession的方法,那么,流程图从SqlSession的地方开始即可,后续都是一样的。

版权提示:文章出自开源中国社区,若对文章感兴趣,可关注我的开源中国社区博客(http://my.oschina.net/zudajun)。(经过网络爬虫或转载的文章,经常丢失流程图、时序图,格式错乱等,还是看原版的比较好)

转载于:https://my.oschina.net/zudajun/blog/670373

Mybatis3.3.x技术内幕(十一):执行一个Sql命令的完整流程相关推荐

  1. SQL Server2000中执行一个SQL, 在lock上发现自己锁自己

    很老的一个数据库, SQL SERVER 2000 SP4,   执行一个查询SQL的时候(查询SQL中有加入nolock), PID=128,   在lock session 上查看 发现 128 ...

  2. mybatis 执行sql_来,全搞懂,原来Mybatis执行一个sql有这么多类型,绝

    Executor 执行器 今天分享一下 Executor.它在框架中是具体sql的执行器,sqlSession(门面模式)封装通用的api,把具体操作委派给 Executor 执行,Executor协 ...

  3. 如何用sqlplus执行一个sql文件和批量执行sql文件

    1.sqlplus执行单个SQL文件 举个例子,假设你的sql文件是test.sql ,保存路径是D:\script,那么在sqlplus里执行它,用如下语法: sqlplus> @D:\scr ...

  4. shell脚本循环执行一个linux命令,Linux中循环执行shell命令的方法

    Linux命令行,循环执行shell命令 死循环 命令格式while true ;do ; done; 可以将 command 替换为任意命令. 下面以echo "hello"; ...

  5. 做一个小程序的完整流程

    一. 引言 最近在帮朋友开发一个小程序,都说今年是小程序快速发展的一年,不懂技术的人,大部分零售店面都开始想做一个小程序帮助推广销售.虽然小程序技术门槛没那么高,但自己独立做一个小程序还是需要了解的内 ...

  6. Mybatis3.4.x技术内幕(二十二):Mybatis一级、二级缓存原理分析

    2019独角兽企业重金招聘Python工程师标准>>> Mybatis的一级缓存,指的是SqlSession级别的缓存,默认开启:Mybatis的二级缓存,指的是SqlSession ...

  7. Mybatis3.3.x技术内幕(十三):Mybatis之RowBounds分页原理

    2019独角兽企业重金招聘Python工程师标准>>> Mybatis可以通过传递RowBounds对象,来进行数据库数据的分页操作,然而遗憾的是,该分页操作是对ResultSet结 ...

  8. 【一个项目开发的完整流程】

    一个软件项目的开发主要包括5个阶段: 需求分析阶段.设计阶段.编码阶段.测试阶段.维护阶段. 以航空订票管理系统为例: 1.项目开发团队成员分工: A.负责系统美工.撰写系统设计规划书.用户使用手册: ...

  9. 往GitLab提交一个自己分支的完整流程

    刚进公司,项目自己负责的部分都是通过自己的分支往主分支去合并提交代码,在这里记录一下如何往 GitLab 中提交自己的分支. 1.下载安装 Git ,运行 Git Bash ,进行安装后的最后一步设置 ...

最新文章

  1. 最最最全面的Java异常面试及解答
  2. Spring事务之Propagation
  3. Maven将中央仓库修改为阿里云的仓库地址
  4. Luogu 3698 [CQOI2017]小Q的棋盘
  5. ocp跟oce的区别 oracle_Oracle视频10g 11g认证视频教程 OCA/OCP 从入门到精通 数据库DBA...
  6. apache如何在虚拟主机中实现用户验证
  7. FluentValidation
  8. C程序设计(第四版)谭浩强著-学习笔记
  9. mac 禁止adobe creative cloud自启动
  10. html5怎么把图片置顶,html/css如何让图片上下居中(居中垂直)?
  11. Matlab 仿真——直流电机速度控制(2)系统分析
  12. NR-PRACH接受端如何检测出preambleid和TA的
  13. 数据库——操作(mysql)
  14. AOP的理解以及实现
  15. 讯飞语音识别之语音转文字------java
  16. Linux基础命令入门
  17. 网页游戏外挂的设计与编写:QQ摩天大楼【一】(基本技术)
  18. 海报创意|十月的节日热点:国庆、重阳和万圣节
  19. PAT 乙级 1069 微博转发抽奖
  20. ubuntu20.04 系统备份以及迁移

热门文章

  1. 高通:蓝牙5.0将可同时连接两个设备
  2. FragmentActivity+FragmentTabHost+Fragement替代TabActibvity+TabHost+Activity
  3. TOJ 4008 The Leaf Eaters
  4. VS2010打开旧版本MFC工程无对话框
  5. 不要让SOA控制我们的思想
  6. 为什么说《让子弹飞》是古今中外的神片
  7. mac java jni_Mac OS上编译JNI的动态库
  8. 大数据分析平台安全的重要性
  9. 选择物联网卡平台时需要重点考虑的标准
  10. Python编程 - 不调用相关choose库函数,“众数“挑选器、随机挑选器 的源码编程实现