Mybatis 动态 SQL

动态 SQL 元素:

  • if
  • choose(when, otherwise)
  • trim(where, set)
  • foreach

1 if

动态 SQL 通常要做的事情是根据条件包含 where 子句的一部分。比如:
1.1 1个条件

<select id="findActiveBlogWithTitleLike" resultType="Blog">
 select * from blog where state = "ACTIVE" 
 <if test="title != null">and title like #{title}</if>
</select>

注意 if 的条件是以 String 的形式作为 test 属性的值的。
1.2 多个条件

<if test="title != null and author.name != null">and title like #{title}</if>

注意传入的 Map 在条件中表达为 author.name,即 Map.key 的形式

2 choose ... when ... otherwise ...

choose ... when ... otherwise ... 映射成 Java 语法就是 switch ... case ... default...

应用场景:当不想应用所有的条件语句,而是根据条件选择其中一项。

<select id="findActiveBlogLike" resultType="Blog">
    select * from blog where state='ACTIVE'
    <choose>
        <when test="title !=null">
            and title like #{title}
        </when>
        <otherwise>
            and featured = 1
        </otherwise>
    </choose>
</select>

3 trim, where, set

只使用 if 语句带来的问题:

<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>

当所有条件都不成立时,此语句变成了select * from blog where

针对这种条件都不成立时拼接的 SQL 出错,有三种解决办法:
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>
  </where>
</select>

3.2 set 用来解决动态更新

<update id="updateAuthorIfNecessary">
    update author
    <set>
        <!--不要忘了逗号-->
        <if test="username != null">username=#{username},</if>
        <if test="password != null">password=#{password},</if>
        <if test="bio != null">bio=#{bio}</if>
    </set>
    where id=#{id}
</update>

3.3 trim
其实 where 和 set 都是 trim 的语法糖,where 和 set 的功能都可以用 trim 来表示

where 相当于

<trim prefix="where" prefixOverrides="AND/OR">

set 相当于

<trim prefix="set" suffixOverrides=",">

trim 标签有4个属性:

(其实无论是那个标签,它的作用都是把标签内部的 SQL 按照一定规则拼接起来,
然后再和标签外边的 SQL 拼接,最终形成完整的 SQL 语句)

  • prefix,前缀,trim 标签体中拼接字符串后的结果,prefix 会给这个结果加上一个前缀,如果 prefix = "where", 则加上 "where"
  • prefixOverrides, 前缀覆盖,去掉拼接结果的前缀
  • suffix, 后缀,它给拼接结果加上一个后缀,比如可以加上limit/order by
  • suffixOverrides, 后缀覆盖,去掉拼接结果的后缀,比如 set 中的“,”

Mybatis 传入参数为 list/array

传入参数为 list/array 时,在拼装成 sql 语句时还需要把它们取出来。这就需要使用 foreach。

foreach 在构建 in 条件中,它可以在 sql 语句中对集合进行迭代。

foreach 元素的属性

名称 作用
item 集合中每一个元素进行迭代时的别名
index 在迭代过程中,每次迭代到的位置
open 该语句以什么开始
separator 迭代元素之间的分隔符
close 该语句以什么结束
collection ???

例子

  1. 实体
public class Employees {  
    private Integer employeeId;  
    private String firstName;  
    private String lastName;  
    private String email;  
    private String phoneNumber;  
    private Date hireDate;  
    private String jobId;  
    private BigDecimal salary;  
    private BigDecimal commissionPct;  
    private Integer managerId;  
    private Short departmentId;  
}    
  1. dao 层
public interface EmployeesMapper {   
  
    List<Employees> getEmployeesListParams(List<String> employeeIds);  
  
    List<Employees> getEmployeesArrayParams(String[] employeeIds);  
  
    List<Employees> getEmployeesMapParams(Map<String,Object> params);  
}  
  1. sql
<select id="getEmployeesListParams" resultType="Employees">  
        select *  
        from EMPLOYEES e  
        where e.EMPLOYEE_ID in  
        <foreach collection="list" item="employeeId" index="index"  
            open="(" close=")" separator=",">  
            <!--注意这个变量名 employeeId 是代表的 item,需要和 item 保持一致-->
            #{employeeId}  
        </foreach>  
    </select>  
    
<select id="getEmployeesArrayParams" resultType="Employees">  
        select *  
        from EMPLOYEES e  
        where e.EMPLOYEE_ID in  
        <foreach collection="array" item="employeeId" index="index"  
            open="(" close=")" separator=",">  
            #{employeeId}  
        </foreach>  
    </select>  
    
<select id="getEmployeesMapParams" resultType="Employees">  
        select *  
        from EMPLOYEES e  
        <where>  
            <if test="departmentId!=null and departmentId!=''">  
                e.DEPARTMENT_ID=#{departmentId}  
            </if>  
            <if test="employeeIdsArray!=null and employeeIdsArray.length!=0">  
                AND e.EMPLOYEE_ID in  
                <foreach collection="employeeIdsArray" item="employeeId"  
                    index="index" open="(" close=")" separator=",">  
                    #{employeeId}  
                </foreach>  
            </if>  
        </where>  
    </select>  

Mybatis 动态 SQL

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 224,861评论 6 522
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 96,263评论 3 402
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 172,033评论 0 366
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 60,999评论 1 300
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 70,000评论 6 400
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 53,483评论 1 314
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 41,850评论 3 428
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 40,827评论 0 279
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 47,366评论 1 324
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 39,404评论 3 346
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 41,525评论 1 355
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 37,130评论 5 351
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,853评论 3 338
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 33,293评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 34,426评论 1 276
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 50,082评论 3 381
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 46,590评论 2 366

推荐阅读更多精彩内容

  • 使用 jdbc 或类似的框架,动态拼接 SQL 是很痛苦的。比如根据当前日期选择数据表、根据传入的参数决定更新哪些...
    程序之心阅读 524评论 0 0
  • MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据...
    jackcooper阅读 495评论 0 1
  • 在mybtis中动态sql主要用到的几个节点元素有: 1、if2、choose(when, otherwise)3...
    Dl_毛良伟阅读 918评论 0 2
  • 、 、 、 :trim标签主要就是标记的作用,可以去掉if条件不满足时多余的and或者or或者,等等,和set标...
    小沙鹰168阅读 1,996评论 0 0
  • 我想象不出 作者:海桑 我想象不出 灵魂是什么形状 什么颜色 它可有体温,香味几何 如果我起身向它问好 它可报我以...
    已丑草阅读 266评论 0 0