MyBatis 源码分析——动态SQL语句

有几年开发经验的程序员应该都有暗骂过原生的SQL语句吧。因为他们不能一句就搞定一个业务,往往还要通过代码来拼接相关的SQL语句。相信大家会理解SQL里面的永真(1=1),永假(1=2)的意义吧。所以mybatis动态SQL功能在笔者看来是最引吸人的。为了更好的区别XML映射文件上的SQL语句。mybatis把SQL语句分为四类。那么这个笔者已经在前面的章节里面讲过了。但是我们在开发过程中常常用到的也就俩种:静态和动态。

关于静态和动态的定义,笔者是这样子理解的——静态SQL语句显示就是里面没有相关的罗辑。即是没有#if之类的语活。反之则是动态SQL语句。而笔者感兴趣是动态SQL部分。我们都知道在读取XML映射文件信息的时候就会分析当前的SQL语句属于哪一种类型。这部分工作就是放在源码的XMLScriptBuilder类里面。

 1  public SqlSource parseScriptNode() {
 2     List<SqlNode> contents = parseDynamicTags(context);
 3     MixedSqlNode rootSqlNode = new MixedSqlNode(contents);
 4     SqlSource sqlSource = null;
 5     if (isDynamic) {
 6       sqlSource = new DynamicSqlSource(configuration, rootSqlNode);
 7     } else {
 8       sqlSource = new RawSqlSource(configuration, rootSqlNode, parameterType);
 9     }
10     return sqlSource;
11   }

看到了吧,是通过成员isDynamic的值来获取相关类型的SQL语句类。DynamicSqlSource类从字面上来讲就很容易看出来是属于动态的。而下面便是静态的。关键的部分还是在parseDynamicTags方法里面。

为了实现动态SQL语句的功能。mybatis设置几个动态的节点。如if,choose 等。当然如果你们想要知道有几个的话,最好跟笔者一样子点开他相关的DTD文件。如下

<!ELEMENT select (#PCDATA | include | trim | where | set | foreach | choose | if | bind)*>

我们可以看到include 、trim 、where 、set 、foreach 、choose 、if 、bind。各自的用法在官网上面有些详细的说明。 大家可以去看看。相信大家看到这里心里应该有了一定的想法。为了实现动态SQL,那么mybatis一定会根据不同的节点来做不同的逻辑处理。这也是笔者为什么说——关键的部分还是在parseDynamicTags方法里面。因为parseDynamicTags方法是用于分析当前select或是delete等节点的SQL节点(即是SqlNode类)。可以说终于生成的SQL语句就是靠这若干个SqlNode类提供生成的。在前面几章中我们有讲到关于BoundSql类的作用。在这里就一下明白了。如下图

通过parseDynamicTags方法分析出需要用到的若干个SqlNode类。并确定他是否是动态SQL语句。如果是,就创建DynamicSqlSource类。而DynamicSqlSource类会存放在MappedStatement类里面。当我们要通过BoundSql类来生成StatementHandler实例的时候,就会从通过MappedStatement类获得对应的BoundSql类。而BoundSql类的getSql方法就会我们最终的落点。

其实笔者的内心是有一点小失望的。我本以为mybatis会一直实现自己的元素处理。当然这只是笔者内心的一点完美主义吧。正如官网上讲的MyBatis 采用功能强大的基于 OGNL 的表达式来消除其他元素。所以我们可以源码里面看到ognl的应用。

 Map<Object, OgnlClassResolver> context = Ognl.createDefaultContext(root, new OgnlClassResolver());

对于ongl笔者就不想多说了。有兴趣的读者们可以自己去看一下。笔者建议还是去看一下吧。struts2框架里面也用到他了。

关于mybatis系列笔者就记录到这里了。希望对大家有用。

时间: 2024-10-15 22:24:45

MyBatis 源码分析——动态SQL语句的相关文章

MyBatis 源码分析——动态代理

MyBatis框架是如何去执行SQL语句?相信不只是你们,笔者也想要知道是如何进行的.相信有上一章的引导大家都知道SqlSession接口的作用.当然默认情况下还是使用DefaultSqlSession类.关于SqlSession接口的用法有很多种.笔者还是比较喜欢用getMapper方法.对于getMapper方法的实现方式.笔者不能下一个定论.笔者只是想表示一下自己的理解而以--动态代理. 笔者把关于getMapper方法的实现方式理解为动态代理.事实上笔者还想说他可以是一个AOP思想的实现

MyBatis源码分析-SQL语句执行的完整流程

MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录.如何新建MyBatis源码工程请点击MyBatis源码分析-IDEA新建MyBatis源码工程. MyBatis框架主要完成的是以下2件事情: 根据JD

【MyBatis源码分析】环境准备

前言 之前一段时间写了[Spring源码分析]系列的文章,感觉对Spring的原理及使用各方面都掌握了不少,趁热打铁,开始下一个系列的文章[MyBatis源码分析],在[MyBatis源码分析]文章的基础之上,可以继续分析数据库连接池.Spring整合MyBatis源码.Spring事物管理tx等等. [MyBatis源码分析]整个文章结构相较[Spring源码分析]稍微改一改,后者会在每一部分源码分析的开头列出要分析的源码的实例,比如: 分析Bean流程加载,就会先写Bean的代码示例及xml

MyBatis 源码分析 - 插件机制

1.简介 一般情况下,开源框架都会提供插件或其他形式的拓展点,供开发者自行拓展.这样的好处是显而易见的,一是增加了框架的灵活性.二是开发者可以结合实际需求,对框架进行拓展,使其能够更好的工作.以 MyBatis 为例,我们可基于 MyBatis 插件机制实现分页.分表,监控等功能.由于插件和业务无关,业务也无法感知插件的存在.因此可以无感植入插件,在无形中增强功能. 开发 MyBatis 插件需要对 MyBatis 比较深了解才行,一般来说最好能够掌握 MyBatis 的源码,门槛相对较高.本篇

Mybatis源码分析

MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录.如何新建MyBatis源码工程请点击MyBatis源码分析-IDEA新建MyBatis源码工程. MyBatis框架主要完成的是以下2件事情: 根据JD

mybatis源码分析(四) mybatis与spring事务管理分析

mybatis源码分析(四) mybatis与spring事务管理分析 一丶从jdbc的角度理解什么是事务 从mysql获取一个连接之后, 默认是自动提交, 即执行完sql之后, 就会提交事务. 这种事务的范围是一条sql语句. 将该连接设置非自动提交, 可以执行多条sql语句, 然后由程序决定是提交事务, 还是回滚事务. 这也是我们常说的事务. Connection connection = dataSource.getConnection(); // connection.setTransa

MyBatis源码分析-MyBatis初始化流程

MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简单的 XML 或注解,将接口和 Java 的 POJOs(Plain Old Java Objects,普通的 Java对象)映射成数据库中的记录.如何新建MyBatis源码工程请点击MyBatis源码分析-IDEA新建MyBatis源码工程. MyBatis初始化的过程也就是创建Configura

【MyBatis源码分析】select源码分析及小结

示例代码 之前的文章说过,对于MyBatis来说insert.update.delete是一组的,因为对于MyBatis来说它们都是update:select是一组的,因为对于MyBatis来说它就是select. 本文研究一下select的实现流程,示例代码为: 1 public void testSelectOne() { 2 System.out.println(mailDao.selectMailById(8)); 3 } selectMailById方法的实现为: 1 public M

MyBatis 源码分析 - 配置文件解析过程

* 本文速览 由于本篇文章篇幅比较大,所以这里拿出一节对本文进行快速概括.本篇文章对 MyBatis 配置文件中常用配置的解析过程进行了较为详细的介绍和分析,包括但不限于settings,typeAliases和typeHandlers等,本文的篇幅也主要在对这三个配置解析过程的分析上.下面,我们来一起看一下本篇文章的目录结构. 从目录上可以看出,2.3节.2.5节和2.8节的内容比较多.其中2.3节是关于settings配置解析过程的分析,除了对常规的 XML 解析过程分析,本节额外的分析了元