MyBatis的强大特性之一就是它的动态SQL,它可以根据不同的条件动态地组成SQL语句进行执行。为此,MyBatis提供了一系列强大的表达式,本章将就此进行学习,主要内容直接参考的是官方文档《动态 SQL》。

1、if

某些条件我需要时才出现,不需要时就不出现,这种需求常常出现在根据用户输入的条件进行搜索的场景,下面来看官方给出的例子:
<select id="findActiveBlogWithTitleLike" resultType="Blog">
SELECT * FROM BLOG
WHERE state = 'ACTIVE'
<if test="title != null">
AND title LIKE #{title}
</if>
</select>
7
 
1
<select id="findActiveBlogWithTitleLike" resultType="Blog">
2
    SELECT * FROM BLOG
3
    WHERE state = 'ACTIVE'
4
    <if test="title != null">
5
        AND title LIKE #{title}
6
    </if>
7
</select>

如果传入了title,那么就会对“title”进行模糊查询返回结果。你甚至可以多条件考虑:
<select id="findActiveBlogLike" resultType="Blog">
SELECT * FROM BLOG WHERE state = 'ACTIVE'
<if test="title != null">
AND title like #{title}
</if>
<if test="author != null and author.name != null">
AND author_name like #{author.name}
</if>
</select>
9
 
1
<select id="findActiveBlogLike" resultType="Blog">
2
    SELECT * FROM BLOG WHERE state = 'ACTIVE'
3
    <if test="title != null">
4
        AND title like #{title}
5
    </if>
6
    <if test="author != null and author.name != null">
7
        AND author_name like #{author.name}
8
    </if>
9
</select>

2、choose / when / otherwise

choose / when / otherwise 三种元素结合起来使用,类似于Java中的switch语句,看了下面这个例子我想你一定能明白:
<select id="findActiveBlogLike" resultType="Blog">
SELECT * FROM BLOG WHERE state = 'ACTIVE'
<choose>
<when test="title != null">
AND title like #{title}
</when>
<when test="author != null and author.name != null">
AND author_name like #{author.name}
</when>
<otherwise>
AND featured = 1
</otherwise>
</choose>
</select>
14
 
1
<select id="findActiveBlogLike" resultType="Blog">
2
    SELECT * FROM BLOG WHERE state = 'ACTIVE'
3
    <choose>
4
        <when test="title != null">
5
            AND title like #{title}
6
        </when>
7
        <when test="author != null and author.name != null">
8
            AND author_name like #{author.name}
9
        </when>
10
        <otherwise>
11
            AND featured = 1
12
        </otherwise>
13
    </choose>
14
</select>

3、where / set / trim

3.1 where

我们先看下面这个例子:
<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>
</select>
13
 
1
<select id="findActiveBlogLike" resultType="Blog">
2
    SELECT * FROM BLOG
3
    WHERE
4
    <if test="state != null">
5
        state = #{state}
6
    </if>
7
    <if test="title != null">
8
        AND title like #{title}
9
    </if>
10
    <if test="author != null and author.name != null">
11
        AND author_name like #{author.name}
12
    </if>
13
</select>

看似没有什么毛病,但假如所有的 if 条件都没有符合怎么办?SQL语句会变成这样:SELECT * FROM BLOG WHERE,这显然是个错误的语句。假设只匹配了第二个 if,那么语句又会变成这样:SELECT * FROM BLOG WHERE AND title like ‘someTitle’,这显然也是个错误的语句。

为了解决上面的问题,你可以使用 where 元素,就像下面这样:
<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>
14
 
1
<select id="findActiveBlogLike" resultType="Blog">
2
    SELECT * FROM BLOG
3
    <where>
4
        <if test="state != null">
5
            state = #{state}
6
        </if>
7
        <if test="title != null">
8
            AND title like #{title}
9
        </if>
10
        <if test="author != null and author.name != null">
11
            AND author_name like #{author.name}
12
        </if>
13
    </where>
14
</select>

有了 where 元素,你不必专门再写WHERE关键字,它会在至少一个子元素条件满足的情况下插入到SQL语句中,甚至你开头写的是 “AND” 或 “OR”,where 元素也会将它们去掉。

3.2 set

类似于 where 元素,用在 update 语句中的动态解决方案叫做 set,看如下例:
<update id="updateAuthorIfNecessary">
update Author
<set>
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</set>
where id=#{id}
</update>
10
 
1
<update id="updateAuthorIfNecessary">
2
    update Author
3
    <set>
4
        <if test="username != null">username=#{username},</if>
5
        <if test="password != null">password=#{password},</if>
6
        <if test="email != null">email=#{email},</if>
7
        <if test="bio != null">bio=#{bio}</if>
8
    </set>
9
    where id=#{id}
10
</update>

如上例,set 元素会动态前置 SET 关键字,同时会删掉无关的逗号(比如只有第二个 if 满足条件的时候)

3.3 trim

trim 元素则是一个能够灵活设置的元素,你甚至可以通过 trim 实现和 where 或 set 元素相同的功能。trim 元素有四个属性:
  • prefix
  • prefixOverride
  • suffix
  • suffixOverride

prefix 表示 “在前置添加的内容”,prefixOverride 则表示 “覆盖掉前置内容并添加prefix的内容”,注意,这些属性的作用都是当trim标签内有SQL语句内容时才会触发。suffix 同理,不过是针对后置的。

多说无益,来看例子:
<select id="findActiveBlogLike" resultType="Blog">
SELECT * FROM BLOG
<trim prefix="WHERE" prefixOverrides="AND |OR">
<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>
</trim>
</select>
14
 
1
<select id="findActiveBlogLike" resultType="Blog">
2
    SELECT * FROM BLOG
3
    <trim prefix="WHERE" prefixOverrides="AND |OR">
4
        <if test="state != null">
5
            state = #{state}
6
        </if>
7
        <if test="title != null">
8
            AND title like #{title}
9
        </if>
10
        <if test="author != null and author.name != null">
11
            AND author_name like #{author.name}
12
        </if>
13
    </trim>
14
</select>

上例中trim的使用结果就是,它等同于 where 元素的效果,即:当有SQL语句出现(如上例有 if 满足),前置内容会添加 “WHERE”,如果遇到前置内容是 “AND ” 或者 “OR” 开头,则先覆盖掉前置内容(也即删掉),再添加 prefix 的内容 “WHERE”。

同理,我们也可以利用 trim 的 prefix 和 suffixOverride 来实现 set 元素的效果:
<update id="updateAuthorIfNecessary">
update Author
<trim prefix="SET" suffixOverrides=",">
<if test="username != null">username=#{username},</if>
<if test="password != null">password=#{password},</if>
<if test="email != null">email=#{email},</if>
<if test="bio != null">bio=#{bio}</if>
</trim>
where id=#{id}
</update>
x
10
 
1
<update id="updateAuthorIfNecessary">
2
    update Author
3
    <trim prefix="SET" suffixOverrides=",">
4
        <if test="username != null">username=#{username},</if>
5
        <if test="password != null">password=#{password},</if>
6
        <if test="email != null">email=#{email},</if>
7
        <if test="bio != null">bio=#{bio}</if>
8
    </trim>
9
    where id=#{id}
10
</update>

4、foreach

动态SQL还可以对集合进行遍历,这在构建IN条件语句,或者是批量插入内容时极为常见:
<select id="selectPostIn" resultType="domain.blog.Post">
SELECT *
FROM POST P
WHERE ID in
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
</select>
 
1
<select id="selectPostIn" resultType="domain.blog.Post">
2
    SELECT *
3
    FROM POST P
4
    WHERE ID in
5
    <foreach item="item" index="index" collection="list" open="(" separator="," close=")">
6
        #{item}
7
    </foreach>
8
</select>

其中:
  • item - 当前迭代的元素
  • index - 当前迭代的次数(如果集合是Map,则index为键)
  • open - 开头字符串
  • separator - 元素间的分隔符
  • close - 结尾字符串

如上最终会形成诸如 “... WHERE ID in ( 10, 12, 23, 35, 99 )” 形式的SQL语句。 


[05] 动态SQL的更多相关文章

  1. 05—动态sql

    1.创建表 CREATE TABLE tb_employee ( ID INT(11) PRIMARY KEY AUTO_INCREMENT, loginname VARCHAR(18), PASSW ...

  2. 游标、动态sql、异常

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAlIAAAFeCAIAAADBl2bCAAAgAElEQVR4nOyddXgU197H12OEELxIkV

  3. mybatis——动态sql

    MyBatis的动态SQL是基于OGNL表达式的,它可以帮助我们方便的在SQL语句中实现某些逻辑. MyBatis中用于实现动态SQL的元素主要有: if choose(when,otherwise) ...

  4. IBATIS动态SQL

    转自:http://www.cnblogs.com/phoebus0501/archive/2011/05/16/2048126.html 直接使用JDBC一个非常普遍的问题就是动态SQL.使用参数值 ...

  5. 动态游标(例如表名作为参数)以及动态SQL分析

    表名作为参数的动态游标 DECLARE v_table_name VARCHAR2(30) := 'CUX_MES_WIP_BARCODE_MAP'; --l_rec SYS_REFCURSOR; T ...

  6. db2存储过程动态sql被截断

    编写存储过程,使用动态sql时,调试时发现变量赋值后被截断. 关键代码如下: 实现的效果是先把上下游做对比的sql语句和相关参数存入RKDM_DATA_VOID_RULE, 执行存储过程后把两个sql ...

  7. (2.3)DDL增强功能-流程化控制与动态sql

    1.流程控制 在T-SQL中,与流程控制语句相关的关键字有8个: BEGIN...END BREAK GOTO CONTINUE IF...ELSE WHILE RETURN WAITFOR 其实还可 ...

  8. (转)Oracle中动态SQL详解

    本文转载自:http://www.cnblogs.com/gaolonglong/archive/2011/05/31/2064790.html 1.静态SQLSQL与动态SQL Oracle编译PL ...

  9. 使用Oracle的DBMS_SQL包执行动态SQL语句

    引用自:http://blog.csdn.net/ggjjzhzz/archive/2005/10/17/507880.aspx 在某些场合下,存储过程或触发器里的SQL语句需要动态生成.Oracle ...

随机推荐

  1. Sybase SQL anywhere5.5

    https://github.com/mono/old-code https://wiki.scn.sap.com/wiki/display/SQLANY/SQL+Anywhere+and+Micro ...

  2. 【读书笔记】iOS-Interface Builder

    IBOutlet或IBAction符号对编译不产生任何影响,它们只是标记,用于告诉Xcode这些对象可以和UI控件进行关联,以便于在编辑Interface Builder上的UI控件的时候Xcode可 ...

  3. Autoit3操作网页实现自动化

    Autoit3 本身有内置的用户自定义函数IE.au3,只限于IE浏览器,如果是Firefox浏览器需要另外自定义函数. 找了很多资料发现有个FF.au3的自定义函数,下载地址 http://www. ...

  4. recovery log直接输出到串口

    我们在调试recovery升级的时候,我们经常需要查看recovery的log,google的原始逻辑中,recovery的log并非直接输出到串口,我们需要输入命令才能获取,我们有三种方式: 第一种 ...

  5. [20171225]RMAN-06808: SECTION SIZE cannot be used when piece limit is in effect.txt

    [20171225]RMAN-06808: SECTION SIZE cannot be used when piece limit is in effect.txt --//朋友拿我的一些例子来测试 ...

  6. 17秋 软件工程 第六次作业 Beta冲刺 Scrum2

    17秋 软件工程 第六次作业 Beta冲刺 Scrum2 我们组转会成员:杰麟: 我们组新成员:宏庆. 各个成员冲刺期间完成的任务 世强:完成分页功能的演示: 陈翔:完成超级管理员后端login模块: ...

  7. 类的反射_reflex

    JAVA反射机制 JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功能称为j ...

  8. Mac OS X 下优化 Terminal,一篇就够了!

    先上最终效果图: 目录 目录 1. 相关工具介绍 2. 配置总览 3. 安装步骤 3.1. 安装 iTerm2 3.2. 安装XCode's Command line tools 3.3. 检查 zs ...

  9. Android Studio打开SDK更新对话框

    再进行android自动化时,有时需要用到android的一些api,但苦于找不到 api文档,各种论坛查看是否有自己所需要的api,甚是麻烦.下面介绍如何通过 android studio将 and ...

  10. final 关键字的作用及应用案例

    final关键字的作用如下: 1.可以修饰成员变量,但不能对该成员变量进行修改: 2.可以修饰局部变量,但不能地该局部变量进行修改: 3.可以修饰成员方法(继承),但不能对父类成员方法进行重写: 4. ...