MyBatis 动态 SQL

如果使用JDBC或者类似于Hibernate的其他框架,很多时候要根据需要去拼装SQL,这是一个麻烦的事情。因为某些查询需要许多条件,比如查询角色,可以根据角色名称或者备注等信息查询,当不输入名称时使用名称作条件就不合适了。通常使用其他框架需要使用名称条件就不合适了。通常使用其他框架需要大量的Java代码进行判断,可读性比较差,而MyBatis提供对SQL语句动态的组装能力,使用XML的几个简单的元素,便能完成动态SQL的功能。大量的判断都可以在MyBatis的映射XML里面配置,以达到许多需要大量代码才能实现的功能,大大减少了代码量,这体现了MyBatis的灵活、高度可配置性和可维护性。

概述

MyBatis的动态SQL包括一下几种元素。

元素 作用 备注
if 判读语句 单条件分支判断
choose(when,otherwise) 相当于java中的switch和case语句 多条件分支判断
trime(where,set) 辅助元素,用于处理特定的SQL拼装问题,比如去掉多余的and、or等 用于处理SQL拼装成的问题
forearch 循环语句 在in语句等列举条件常用

动态SQL实际使用的元素并不多,但是他们带来了灵活性,减少了许多工作量的同时,也在很大程度上提高了程序的可读性和可维护性。

if元素

if元素是最常用的判断语句,相当于Java中的if语句,他尝尝与test属性联合使用。
if元素十分简单,举例说明如何使用它。先进行简单的场景描述:根据角色名名称去查找角色,但是角色名称是一个选填条件,不填写时,就不要用做它作为条件查询。这是查询中最常见的场景之一。

<select id="findRoles" parameterType="string" resultMap="roleResultMap">
select * from t_role where 1=1
<if test="roleName != null and roleName !=''">
    and role_name like concat('%',#{roleName}, '%')
</if>
</select>

choose when otherwise 元素

上边的代码中相当于 java 语言中的 if 语句,不是这个就是那个。有时候还需要第三种选择,甚至更多选择,也就是类似 switch-case-default 功能的语句。在映射器的动态语句中 choose、when、otherwise 这三个元素承担了这个功能。假设有这样一个场景:

  • 如果角色编号不为空,则只用角色编号作为查询条件
  • 当角色编号为空,而角色名称不为空,则用角色名称作为条件进行模糊查询。
  • 当角色编号和角色名称都为空,则要求角色备注不为空。

这个场景可能有点不切实际,这里主要集中于如何使用动态元素来实现它。

<select id="findRoles" parameterType="role" resultMap="roleResultMap">
select role_no,role_name,note from t_role
where 1=1
<choose>
    <when test="roleNo != null and roleNo !=''">
        and role_no = #{roleNo}
    </when>
    <when test="roleName != null and roleNo !=''">
        and role_name like concat('%',#{roleName}, '%')
    </when>
    <otherwise>
        and note is not null
    </otherwise>
</choose>
</select>

trim、 where、set 元素

细心的话,可以发现上边的SQL语句的动态元素SQL中都加入了一个条件 “1=1” 如果没有这个条件,那么可能就会变成了一条错误的语句。

MyBatis 有一个简单的处理,这在 90% 的情况下都会有用。而在不能使用的地方,你可以自定义处理方式来令其正常工作。一处简单的修改就能达到目的:

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG
  <where>
    <if test="state != null">
         state = #{state}
    </if>
    <if test="title != null">
        AND title like #{title}
    </if>
    <if test="author != null and author.name != null">
        AND author_name like #{author.name}
    </if>
  </where>
</select>

where 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。而且,若语句的开头为“AND”或“OR”,where 元素也会将它们去除。

更多动态SQL的特性可以到MyBatis官方文档查看。

posted @ 2019-03-28 17:56  这块显卡有点冷  阅读(...)  评论(... 编辑 收藏