mybatis作为持久层,其操作数据库离不开sql语句。而BoundSql则是其保存Sql语句的对象

前提

  1. 针对mybatis的配置文件的节点解析,比如where/if/trim的节点解析可见文章Spring mybatis源码篇章-NodeHandler实现类具体解析保存Dynamic sql节点信息

  2. 针对mybatis配置文件的解析帮助类SqlSource[一般为DynamicSqlSource]的使用可见文章Spring mybatis源码篇章-XMLLanguageDriver解析sql包装为SqlSource

  3. 对BoundSql对象的调用获取可见文章Mybatis源码分析-BaseExecutor

本文将在上述的知识前提下展开对Sql语句的解析

BoundSql的引用

主要是通过MappedStatement#getBoundSql()方法调用获取的。我们可以简单跟踪下其中的源码,如下

  public BoundSql getBoundSql(Object parameterObject) {
// 通过SqlSource获取BoundSql对象
BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
// 校验当前的sql语句有无绑定parameterMapping属性
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
if (parameterMappings == null || parameterMappings.isEmpty()) {
boundSql = new BoundSql(configuration, boundSql.getSql(), parameterMap.getParameterMappings(), parameterObject);
} // check for nested result maps in parameter mappings (issue #30)
for (ParameterMapping pm : boundSql.getParameterMappings()) {
String rmId = pm.getResultMapId();
if (rmId != null) {
ResultMap rm = configuration.getResultMap(rmId);
if (rm != null) {
hasNestedResultMaps |= rm.hasNestedResultMaps();
}
}
} return boundSql;
}

RawSqlSource-常用的mybatis解析sql帮助类

我们观察下其getBoundSql()方法,源码如下

  public BoundSql getBoundSql(Object parameterObject) {
//此处的sqlSource为RawSqlSource的内部属性
return sqlSource.getBoundSql(parameterObject);
}

我们看下sqlSource是如何生成的,由此观察其构造函数

public RawSqlSource(Configuration configuration, String sql, Class<?> parameterType) {
// 通过SqlSourceBuilder来创建sqlSource
SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
Class<?> clazz = parameterType == null ? Object.class : parameterType;
sqlSource = sqlSourceParser.parse(sql, clazz, new HashMap<String, Object>());
}

#{}的使用这里稍微提下,一般的写法都为{name,jdbcType=String,mode=out,javaType=java.lang.String...},其中jdbcType也可以不指定,系统会自动识别。上述的代码其实主要就是针对#{}字符内容的处理

注意:${}这样的字符是通过DynamicSqlSource来完成解析的,具体的解析读者可自行分析

我们可以继续看下SqlSourceBuilder类是如何解析获取sql语句的

SqlSourceBuilder#parse()

直接上源码

public SqlSource parse(String originalSql, Class<?> parameterType, Map<String, Object> additionalParameters) {
// 对#{}这样的字符串内容的解析处理类
ParameterMappingTokenHandler handler = new ParameterMappingTokenHandler(configuration, parameterType, additionalParameters);
GenericTokenParser parser = new GenericTokenParser("#{", "}", handler);
// 获取真实的可执行性的sql语句
String sql = parser.parse(originalSql);
// 包装成StaticSqlSource返回
return new StaticSqlSource(configuration, sql, handler.getParameterMappings());
}

简单的看下ParameterMappingTokenHandler是如何解析的,其是TokenHandler接口的实现类,我们就关注实现方法handleToken

@Override
public String handleToken(String content) {
// 此处的作用就是对`#{}`节点中的key值保存映射,比如javaType/jdbcType/mode等信息,限于篇幅过长,读者可自行分析
parameterMappings.add(buildParameterMapping(content));
// 将`#{}`替换为?,即一般包装成`select * form test where name=? and age=?`预表达式语句
return "?";
}

上述主要通过ParameterMappingTokenHandler类来完成对#{}字符串的解析,其中的映射信息则保存至BoundSql的parameterMappings属性中

总结

  1. BoundSql语句的解析主要是通过对#{}字符的解析,将其替换成?。最后均包装成预表达式供PrepareStatement调用执行

  2. #{}中的key属性以及相应的参数映射,比如javaType、jdbcType等信息均保存至BoundSql的parameterMappings属性中供最后的预表达式对象PrepareStatement赋值使用

Mybatis源码解析-BoundSql的更多相关文章

  1. Mybatis源码解析-DynamicSqlSource和RawSqlSource的区别

    XMLLanguageDriver是ibatis的默认解析sql节点帮助类,其中的方法其会调用生成DynamicSqlSource和RawSqlSource这两个帮助类,本文将对此作下简单的简析 应用 ...

  2. 【MyBatis源码解析】MyBatis一二级缓存

    MyBatis缓存 我们知道,频繁的数据库操作是非常耗费性能的(主要是因为对于DB而言,数据是持久化在磁盘中的,因此查询操作需要通过IO,IO操作速度相比内存操作速度慢了好几个量级),尤其是对于一些相 ...

  3. Mybatis源码解析,一步一步从浅入深(七):执行查询

    一,前言 我们在文章:Mybatis源码解析,一步一步从浅入深(二):按步骤解析源码的最后一步说到执行查询的关键代码: result = sqlSession.selectOne(command.ge ...

  4. Mybatis源码解析(四) —— SqlSession是如何实现数据库操作的?

    Mybatis源码解析(四) -- SqlSession是如何实现数据库操作的?   如果拿一次数据库请求操作做比喻,那么前面3篇文章就是在做请求准备,真正执行操作的是本篇文章要讲述的内容.正如标题一 ...

  5. Mybatis源码解析(二) —— 加载 Configuration

    Mybatis源码解析(二) -- 加载 Configuration    正如上文所看到的 Configuration 对象保存了所有Mybatis的配置信息,也就是说mybatis-config. ...

  6. mybatis源码-解析配置文件(四-1)之配置文件Mapper解析(cache)

    目录 1. 简介 2. 解析 3 StrictMap 3.1 区别HashMap:键必须为String 3.2 区别HashMap:多了成员变量 name 3.3 区别HashMap:key 的处理多 ...

  7. mybatis源码-解析配置文件(四)之配置文件Mapper解析

    在 mybatis源码-解析配置文件(三)之配置文件Configuration解析 中, 讲解了 Configuration 是如何解析的. 其中, mappers作为configuration节点的 ...

  8. mybatis源码-解析配置文件(三)之配置文件Configuration解析

    目录 1. 简介 1.1 系列内容 1.2 适合对象 1.3 本文内容 2. 配置文件 2.1 mysql.properties 2.2 mybatis-config.xml 3. Configura ...

  9. Mybatis源码解析,一步一步从浅入深(一):创建准备工程

    Spring SpringMVC Mybatis(简称ssm)是一个很流行的java web框架,而Mybatis作为ORM 持久层框架,因其灵活简单,深受青睐.而且现在的招聘职位中都要求应试者熟悉M ...

随机推荐

  1. spring boot admin

    这里记录一个spring cloud的模板,有的模块spring cloud eureka + spring boot admin + spring cloud zuul + 一个普通spring c ...

  2. POJ 2593 Max Sequence

    Max Sequence Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 17678   Accepted: 7401 Des ...

  3. 案例:Standby RAC遭遇ORA-1157,1111,1110导致实例crash处理

    案例:Standby RAC遭遇ORA-1157,1111,1110导致实例crash处理 环境:RHEL 6.5 + Oracle RAC 11.2.0.4 + Dataguard 今天在实验环境的 ...

  4. MYSQL中的多类型查询及高级查询操作

    离散查询select * from car where price=30 or price=40 or price=50 or price=60;select * from car where pri ...

  5. 【技术干货】听阿里云CDN安防技术专家金九讲SystemTap使用技巧

    ​1.简介 SystemTap是一个Linux非常有用的调试(跟踪/探测)工具,常用于Linux 内核或者应用程序的信息采集,比如:获取一个函数里面运行时的变 量.调用堆栈,甚至可以直接修改变量的值, ...

  6. APP测试容易忽略的地方

    我们手机APP测试,主要针对的是android和ios两大主流操作系统,总体上来说android手机型号.版本多,bug也多:ios相对bug少.下面就针对Android说一下最容易忽略的测试点吧. ...

  7. JS模拟类的实现

    http://www.ruanyifeng.com/blog/2012/07/three_ways_to_define_a_javascript_class.html

  8. fedora23安装配置记录

    一.安装fedora 1.下载fedora的镜像文件,个人比较喜欢gnome,因而直接下载工作站版本了! http://start.fedoraproject.org/这个是浏览器首页,提供了fedo ...

  9. Win7系统如何复制CMD命令提示符框中的内容

    Win7系统如何复制CMD命令提示符框中的内容.. Win7系统如何复制CMD命令提示符框中的内容右键命令提示符窗口的标题栏,选择属性. 选择“编辑选项”里的“快速编辑模式”,并确定: 鼠标左键按下选 ...

  10. Kotlin代理属性--官方文档翻译

    代理属性 Delegated Properties 本文为个人翻译的Kotlin官方文档, 原文连接: Delegated Properties 一些特定的常见类型的属性, 尽管我们可以在每次需要的时 ...