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. 【读书笔记】iOS-强类型与弱类型

    id类型是一个通用类型,OC使用id表示任意类型的对象,它可以作为一个占位符表示这是一个不确定的类型的对象或者引用.因此,所有的对象都 可以用id来表示.这很有用,想象一下,如果你需要实现一个通用的链 ...

  2. css清除默认样式

    CSS 清除默认样式   通常有以下几句就够了: *{margin:0;padding:0} li{list-style:none} img{vertical-align:top;border:non ...

  3. JMeter 扩展JMeter插件获取更多监听器

    扩展Jmeter插件获取更多监听器 by:授客 QQ:1033553122 为了获取更多监听器,方便的监控系统及应用,有必要安装第三方插件. 插件下载地址: https://jmeter-plugin ...

  4. 程序员简单打造一个灵活智能的自动化运维系统C#实例程序

    你是一个程序员,被派去管理公司500台计算机.这些机器可能需要执行一些自动化任务,一台台手动操作会把你累死.重复性的工作还是交给电脑处理,怎么解决这个问题呢?一个自动化的运维系统是必须的.自己实现的好 ...

  5. Android中的padding和margin的区别

    在Android的布局中,常常有人将padding和margin搞混,他们其实不一样的,padding是该控件的内部距离. magin是该控件与其他控件之间的距离.例如 <LinearLayou ...

  6. ViewPager防止Fragment销毁以及取消Fragment的预加载

    存在的问题 1. 默认情况下,ViewPager会根据setOffscreenPageLimit()方法设置的大小,自动预加载2. 还是根据setOffscreenPageLimit()方法设置的大小 ...

  7. JDBC-Statement,prepareStatement,CallableStatement的比较

    参考:https://www.cnblogs.com/Lxiaojiang/p/6708570.html JDBC核心API提供了三种向数据库发送SQL语句的类: Statement:使用create ...

  8. [转]js版的md5()

    转自:http://blog.163.com/a_hc/blog/static/1623434200831832441896/ <script language=javascript>/* ...

  9. windows server服务器上mysql远程连接失败的坑

    windows server服务器上mysql远程连接失败的坑 背景:趁这阿里云活动,和朋友合伙买了个服务器,最坑的是没想到他买的是windows Server的,反正便宜,将就着用吧,自己装好了wa ...

  10. JavaScript中遍历数组和对象的方法

    js数组遍历和对象遍历 针对js各种遍历作一个总结分析,从类型用处,分析数组和对象各种遍历使用场景,优缺点等 JS数组遍历: 1,普通for循环,经常用的数组遍历 var arr = [1,2,0,3 ...