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. TCP握手过程中建连接的流程和队列

    这里有两个队列:syns queue(半连接队列):accept queue(全连接队列). 三次握手过程中: 第一步: server 收到 client 的 syn 后,把这个连接信息放到半连接队列 ...

  2. javascript: checked 不可全选

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. csharp:FTP Client Library using FtpWebRequest or Sockets

    https://netftp.codeplex.com/SourceControl/latest http://ftplib.codeplex.com/ https://www.codeproject ...

  4. python之线程相关操作(补充)

    1 线程的其他方法 import threading import time from threading import Thread, current_thread def f1(n): time. ...

  5. SD从零开始66 数据仓库的概念

    [原创] SD从零开始66 数据仓库的概念 数据仓库概念:预览Data Warehouse Concepts:Overview 本单元解释LIS中的数据仓库概念: 详细的解释了该概念的各个层次-介绍了 ...

  6. Salesforce数据安全简介

    数据安全级别 Salesforce中将数据安全分为若干等级: 组织级别:组织级别的安全设定在整个系统内部都有效.这是最广泛的级别 对象级别:对象级别的安全设定可以限制用户对于对象的权限 字段级别:字段 ...

  7. C#中禁止跨线程直接访问控件

    C#中禁止跨线程直接访问控件,InvokeRequired是为了解决这个问题而产生的,当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它.此时它将会在内部调用ne ...

  8. [20171227]表的FULL_HASH_VALUE值的计算.txt

    [20171227]表的FULL_HASH_VALUE值的计算.txt --//sql_id的计算是使用MD5算法进行哈希,生成一个128位的Hash Value,其中低32位作为HASH VALUE ...

  9. [20171106]修改show spparameter的显示宽度.txt

    [20171106]修改show spparameter的显示宽度.txt --//很多年前做的,修改show parameter的显示宽度.--//链接: [20121023]改变show para ...

  10. Cockpit subscriptions on CentOS 7 - This system is not registered with an entitlement server. You can use subscription-manager to register.

    下午安装 cockpit 时,使用 yum 工具的时候哦,出现如下信息: This system is not registered with an entitlement server. You c ...