MyBatis 的秘密动态SQL

动态SQL
说到动态SQL,就不得不提Script,Java作为一个静态语音,代码需要先编译,然后再运行,虽然带来了效率,但是却损失了灵活性。

Spring为此还专门提供了一套SpEL用来封装Java脚本语言API

在MyBatis中,也支持动态SQL,想要将简单的String字符串编译成能运行的代码,需要其他的库的支持,MyBatis内部使用的是OGNL库。

在OgnlCache中,是MyBatis对OGNL的简单封装:

public static Object getValue(String expression, Object root) {
    try {
        Map context = Ognl.createDefaultContext(root, MEMBER_ACCESS, CLASS_RESOLVER, null);
        return Ognl.getValue(parseExpression(expression), context, root);
    } catch (OgnlException e) {
        throw new BuilderException("Error evaluating expression '" + expression + "'. Cause: " + e, e);
    }
}

主要便是增加了一层缓存。
有了上面的基础,我们就可以通过需求,来了解实现了:

在MyBatis中,动态SQL标签有如下几个:

if :通过条件判断执行SQL
choose :通过switch选择一条执行SQL 一般和when / otherwise一起使用
trim : 简单加工SQL,比如去除头尾的逗号等,同类的还有where / set
foreach : 遍历容器,将遍历的结果拼接成SQL
bind : 通过OGNL表达式获取指定的值,并绑定到环境变量中
简单的使用方式如下:

<select id="findActiveBlogWithTitleLike"
     resultType="Blog">
  SELECT * FROM BLOG
  WHERE state = ‘ACTIVE’
  <if test="title != null">
    AND title like #{title}
  </if>
</select>

可以看到,动态SQL的关键就是获取title的值,然后执行test对应的表达式,最后根据结果拼接SQL

最后也是比较重要的一点就是,MyBatis的动态SQL标签是可以嵌套使用的:

比如:

<update id="update" parameterType="User">
   UPDATE users
   <trim prefix="SET" prefixOverrides=",">
       <if test="name != null and name != ''">
           name = #{name}
       </if>
       <if test="age != null and age != ''">
           , age = #{age}
       </if>
       <if test="birthday != null and birthday != ''">
           , birthday = #{birthday}
       </if>
   </trim>
   <where> 1=1
     <if test="id != null">
       and id = ${id}
     </if>
   </where>
</update>

这样的结构,就像是一颗树,需要层层遍历处理。
组合模式
前面说到了MyBatis处理动态SQL的需求,需要处理嵌套的标签。

而这个,恰好符合组合模式的解决场景。

在MyBatis中,处理动态SQL的关键类如下:

SqlNode : 用来表示动态标签的相关信息
NodeHandler : 用来处理SqlNode其他信息的类
DynamicContext : 用来保存处理整个标签过程中,解析出来的信息,主要元素为StringBuilder
SqlSource : 用来表示XML中SQL的信息,MyBatis中,动态SQL最终都会通过SqlSource表示
SqlNode接口的定义如下:

public interface SqlNode {
  //处理目前的信息,并将处理完毕的信息追加到DynamicContext 中  
  boolean apply(DynamicContext context);
}

接下来从MyBaits创建以及使用SqlSource上来分析动态SQL的使用:

创建SqlSource的代码如下:

XMLScriptBuilder#parseScriptNode()

public SqlSource parseScriptNode() {
    //创建组合模式中的根节点
    MixedS
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值