Mybatis源码解析-BoundSql
mybatis作为持久层,其操作数据库离不开sql语句。而BoundSql则是其保存Sql语句的对象
前提
针对mybatis的配置文件的节点解析,比如
where/if/trim的节点解析可见文章Spring mybatis源码篇章-NodeHandler实现类具体解析保存Dynamic sql节点信息针对mybatis配置文件的解析帮助类SqlSource[一般为DynamicSqlSource]的使用可见文章Spring mybatis源码篇章-XMLLanguageDriver解析sql包装为SqlSource
对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属性中
总结
BoundSql语句的解析主要是通过对
#{}字符的解析,将其替换成?。最后均包装成预表达式供PrepareStatement调用执行
#{}中的key属性以及相应的参数映射,比如javaType、jdbcType等信息均保存至BoundSql的parameterMappings属性中供最后的预表达式对象PrepareStatement赋值使用
Mybatis源码解析-BoundSql的更多相关文章
- Mybatis源码解析-DynamicSqlSource和RawSqlSource的区别
XMLLanguageDriver是ibatis的默认解析sql节点帮助类,其中的方法其会调用生成DynamicSqlSource和RawSqlSource这两个帮助类,本文将对此作下简单的简析 应用 ...
- 【MyBatis源码解析】MyBatis一二级缓存
MyBatis缓存 我们知道,频繁的数据库操作是非常耗费性能的(主要是因为对于DB而言,数据是持久化在磁盘中的,因此查询操作需要通过IO,IO操作速度相比内存操作速度慢了好几个量级),尤其是对于一些相 ...
- Mybatis源码解析,一步一步从浅入深(七):执行查询
一,前言 我们在文章:Mybatis源码解析,一步一步从浅入深(二):按步骤解析源码的最后一步说到执行查询的关键代码: result = sqlSession.selectOne(command.ge ...
- Mybatis源码解析(四) —— SqlSession是如何实现数据库操作的?
Mybatis源码解析(四) -- SqlSession是如何实现数据库操作的? 如果拿一次数据库请求操作做比喻,那么前面3篇文章就是在做请求准备,真正执行操作的是本篇文章要讲述的内容.正如标题一 ...
- Mybatis源码解析(二) —— 加载 Configuration
Mybatis源码解析(二) -- 加载 Configuration 正如上文所看到的 Configuration 对象保存了所有Mybatis的配置信息,也就是说mybatis-config. ...
- mybatis源码-解析配置文件(四-1)之配置文件Mapper解析(cache)
目录 1. 简介 2. 解析 3 StrictMap 3.1 区别HashMap:键必须为String 3.2 区别HashMap:多了成员变量 name 3.3 区别HashMap:key 的处理多 ...
- mybatis源码-解析配置文件(四)之配置文件Mapper解析
在 mybatis源码-解析配置文件(三)之配置文件Configuration解析 中, 讲解了 Configuration 是如何解析的. 其中, mappers作为configuration节点的 ...
- mybatis源码-解析配置文件(三)之配置文件Configuration解析
目录 1. 简介 1.1 系列内容 1.2 适合对象 1.3 本文内容 2. 配置文件 2.1 mysql.properties 2.2 mybatis-config.xml 3. Configura ...
- Mybatis源码解析,一步一步从浅入深(一):创建准备工程
Spring SpringMVC Mybatis(简称ssm)是一个很流行的java web框架,而Mybatis作为ORM 持久层框架,因其灵活简单,深受青睐.而且现在的招聘职位中都要求应试者熟悉M ...
随机推荐
- CentOS Linux 新建oracle数据库实例并连接
CentOS Linux 新建oracle数据库实例 安装好oracle之后,首先想到的那就是自己建一个库来看看效果喽. 创建的过程如下文章所说,http://blog.chinaunix.net/u ...
- JUnit4在Eclipse中的使用
测试是项目开发中很重要的一环.实际上,建议的项目前期编写过程是:构思-> 编写单元测试代码-> 编写接口->编写实现类-> 测试实现类->编写主类....JUnit是一个 ...
- NoSession问题
第一种原因: no Session 错误 dao层中get方法换成了load方法,或者其他原因引起. 原因分析: 真正用到代理对象的时候,代理对象没有值,并且session的生命周期已经走完了. 解 ...
- table之thead兼容
今天遇到一个小bug,是关于table中thead,tbody,tfoot的兼容问题: 在开发的时候为了方便写样式,我就把表格的标题部分关于th的内容放在了thead中,当然了,我也没有写tbody和 ...
- Linux修改IP,DNS和网关
以Red Hat Enterprise Linux 5.2为例1.最常用的给网卡配置ip的命令为 #ifconfig eth0 192.168.0.1 netmask 255.255.255.0 up ...
- 【物联网云端对接-2】通过MQTT协议与阿里云物联网套件进行云端通信
在<程序员>杂志2017.4刊上,曾写过一篇<微软百度阿里三大物联网平台探析>,上面曾介绍了阿里云物联网套件的一些内容,在写该篇文章的时候,凌霄物联网网关还无法对接到此平台( ...
- C++11 中值得关注的几大变化(网摘)
C++11 中值得关注的几大变化(详解) 原文出处:[陈皓 coolshell] 源文章来自前C++标准委员会的 Danny Kalev 的 The Biggest Changes in C++11 ...
- Java静态绑定与动态绑定
程序绑定的概念: 绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来.对java来说,绑定分为静态绑定和动态绑定:或者叫做前期绑定和后期绑定. 静态绑定: 在程序执行前方法已经被绑定(也就是说 ...
- css复习内容
有时候 自己动手写一遍比想十遍都有用 <!DOCTYPE html><html> <head> <meta charset="utf-8" ...
- Github 开源:使用 .NET WinForm 开发所见即所得的 IDE 开发环境(Sheng.Winform.IDE)【2.源代码简要说明】
GitHub:https://github.com/iccb1013/Sheng.Winform.IDE 在上一篇文章中,简要的介绍了 Sheng.Winform.IDE 的基本功能和要实现的目标: ...