MyBatis -- 动态sql原理分析

Mybatis 动态 SQL 是做什么的

Mybatis的 动态 SQL 是指在进行 SQL 操作的时候,传入的参数对象或者参数值,根据匹配的条件,有可能需要动态的去判断是否为空,循环,拼接等情况。

动态 SQL 标签

Mybatis 提供了 9 种动态 SQL 标签:

<if/>
<choose/>、<when/>、<otherwise/>
<trim/>、<where/>、<set/>
<foreach/>
<bind/>

还有一种特殊的用于注解形式开发的 <script>

  • <if> if是为了判断传入的值是否符合某种规则,比如是否不为空;
  • <choose> <when> <otherwise>:这是一组组合标签,他们的作用类似于 Java 中的 switch、case、default。只有一个条件生效,也就是只执行满足的条件 when,没有满足的条件就执行 otherwise,表示默认条件;
<!--动态Sql: choose、when、otherwise 标签-->
<select id="getUser" resultType="com.git.pojo.User">
 select * from user
 <where>
   <choose>
     <when test="name != null and name != ''">
       AND name = #{name}
     </when>
     <otherwise>
       AND id = #{id}
     </otherwise>
   </choose>
 </where>
</select>
  • <where> 标签可以用来做动态拼接查询条件,where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。当和if标签配合的时候,不用显示的声明类似where 1=1这种无用的条件;
  • <set> : 功能与<where>类似,主要用于更新操作。为了删除在if不符合判断条件下,多出来的set关键字和”,”。
  • <trim> 标签主要用在当 <where><set> 标签不符合期望的时候,可以自定义返回内容。
    • <trim> 一共有 4个参数:
    • prefix(前缀): 在标签内有内容时,在句首增加的字段。例:where 或者 set
    • prefixOverrides(去掉的第一个标记): 例:and | or
    • suffix(后缀): 在标签内有内容时,在句尾增加的字段。例:order by id
    • suffixOverriides(去掉最后一个标记):例:“,”
  • <foreach> 标签可以把传入的集合对象进行遍历,然后把每一项的内容作为参数传到sql语句中,里面涉及到 item(具体的每一个对象), index(序号), open(开始符), close(结束符), separator(分隔符);
<!--动态Sql: foreach标签, in查询-->
<select id="dynamicSqlSelectList" resultType="com.lagou.pojo.User">
  SELECT * from user WHERE id in
  <foreach collection="list" item="id" open="(" close=")" separator="," >
    #{id}
  </foreach>
</select>
  • <bind> 元素允许你在 OGNL 表达式以外创建一个变量,并将其绑定到当前的上下文。
<bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
  • <script> 是用在带注解的映射器接口类中使用动态 SQL。需要用script标签把所有sql包裹,这样才可以正常使用上面的的各种动态标签.

动态sql的执行原理

动态 SQL 的执行整体分为两个部分:解析执行

一、 SQL 解析

在项目启动 SqlSessionFactory 加载xml配置文件并进行解析,根据关键标签封装成对应的handler处理对象,封装成 sqlSource 对象存在ConfigurationmappedStatement 中。
调用过程:

  1. SqlSessionFactoryBuilderbuilder 方法中,封装XMLConfigBuilder 类,并调用该类的parse() 方法 进行解析。在解析过程中使用到了私有的mapperElement(XNode parent) 方法
  2. mapperElement(XNode parent) 方法 中根据<mapper> 的资源地址获取到每一个mapper的配置文件,并构建XMLMapperBuilder 对象,之后执行解析。
  3. 解析过程中调用 configurationElement 方法中的 buildStatementFromContext 解析 <select /> <insert /> <update /> <delete /> 节点
  4. 遍历以上四种节点,并构建 XMLStatementBuilder 对象,进行解析。
  5. 在解析过程中,使用 langDriver.createSqlSource() 创建 SqlSource

这个 SqlSource 里面就存放着最后解析出来的动态SQL
接下来是创建SqlSource的具体解析过程。

  1. createSqlSource() 中 首先将 节点内容 和 传入参数类型 封装为 XMLScriptBuilder。之后调用解析方法 parseScriptNode()
  2. 在解析方法中执行parseDynamicTags()方法,会对nodeHandlers里的标签根据不同的handler来处理不同的标签。
  3. 最后把 DynamicContext 结果放回SqlSource中
二、 执行

Executor执行的时候,调用 DynamicSqlSource 的解析方法,并返回解析好的BoundSql,和已经排好序,需要替换的参数

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值