MyBatis之动态SQL语句

1、动态SQL语句

在之前我们了解过 Mybatis 的映射文件,那些 SQL 语句都是比较简单的。但有些时候业务逻辑复杂时,我们的 SQL是需要动态变化的,此时在前面的学习中我们的 SQL 就不能满足要求了。动态 SQL 是 MyBatis 的强大特性之一,MyBatis 3 精简用于动态 SQL 语句元素种类,现在主要了解的元素如下:if标签、choose (when, otherwise)标签、trim (where, set)标签和foreach标签

2、if 标签

我们根据实体类的不同取值,使用不同的 SQL语句来进行查询。比如在 id如果不为空时可以根据id查询,如果username 不同空时还要加入用户名作为条件。这种情况在我们的多条件组合查询中经常会碰到。

<select id="findByCondition" parameterType="user" resultType="user">
    select * from User where 
    <if test="id!=0">
        and id=#{id}
    </if>
    <if test="username!=null and username!= '' ">
        and username=#{username}
    </if>
</select>

在上述代码中,如果 id 的属性值不为 0 ,则将 and id=#{id}添加到SQL 语句后,如果 username 的属性值不为 null 且不为 ‘’ 时,则将 and username=#{username}添加到SQL 语句后。其中 test属性就是判断条件。

2、choose、when和otherwise 标签

在有些时候,我们只想在多个条件中选择一个使用。就像 java 中的 switch 语句,一个值只匹配一种结果。在 java 的 switch 语句中有三个关键字:switch、case、default,而 MyBatis 中的也有类似标签, choose、when和otherwise 元素分别与之对应。

<select id="findByCondition" parameterType="user" resultType="user">
    select * from User where 1 = 1
  <choose>
    <when test="age >  12">
      AND age = #{author.name}
    </when>
    <when test="age <  12">
      AND age = 0
    </when>
    <otherwise>
      AND  age = 120
    </otherwise>
  </choose>
</select>

上述代码中,判断 age 的属性值,当 age >12 时使用AND age = #{author.name},当age < 12 时使用AND age = 0,当age = 12 时使用默认语句AND age = 0

3、trim、where和set 标签

在使用if标签时,我们可能会遇到这种问题,当 id 和 username 都不满足条件时,SQL 语句会变成这样:select * from User where;当 id 不满足条件时,SQL 语句会变成这样:select * from User where and username=#{username},这样导致查询失败。


为了解决这类问题, MyBatis 就提供一个where元素标签。where元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除:

<select id="findByCondition" parameterType="user" resultType="user">
    select * from User
  <where>
    <if test="id!=0">
        id=#{id}
    </if>
    <if test="username!=null and username!= '' ">
        and username=#{username}
    </if>
  </where>
</select>

上述代码的执行流程时:判断 id 属性和 username 属性是否满足条件,如果都不满足则不添加 where 子句;如果只有其中一个属性或两个属性都满足条件,则添加 where 子句。当只有 username 属性满足条件时,会将子句的开头为 and 直接去除。

还有另外一个元素set,它主要用于动态包含需要更新的列,使用方法和where元素一样:

<update id="updateUser">
  update Author
    <set>
      <if test="name != null">name =#{name },</if>
      <if test="age != null">age=#{age},</if>
    </set>
  where id=#{id}
</update>

当然如果where元素的功能不够,我们也可以通过trim元素进行自定义,例如在 insert 语句中我们需要自定义插入选项:

<trim prefix="values (" suffix=")" suffixOverrides=",">
  <if test="name!= null">
      #{name},
  </if>
  <if test="age!= null">
      #{age},
  </if>
</trim >

上述代码的执行流程,判断 id 属性和 username 属性的属性值,然后将prefix属性的属性值添加在子句最前面,suffix属性的属性值添加在子句最后面,suffixOverrides属性的属性值表示将子句最后的,逗号去除,子句的中间部分由if元素进行判断。

trim元素还有第四个属性值prefixOverrides,表示将子句开头的指定属性值去掉。suffixOverridesprefixOverrides的作用是一样的,只不过作用的地方不同,且可以通过 | 或指定多个属性值。

通过用 trim 元素替换元素和元素

set 元素和where元素等价的 trim 元素:

<!-- prefixOverrides属性值中间的空格不能省略 -->
<trim prefix="WHERE" prefixOverrides="AND |OR ">
  ...
</trim>

<trim prefix="SET" suffixOverrides=",">
  ...
</trim>

4、foreach 标签

foreach 标签顾名思义就是用于循环,一般用于构建 IN 条件语句和多条语句插入的场景。任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象都可以作为集合参数传递给 foreach 标签。foreach 标签有几个属性值:

  • collection:用于指定集合类型
  • open:用于指定子句的开头
  • close:用于指定子句的结尾
  • separator:用于指定集合每个元素之间的分隔符
  • item:用于指定循环的当前集合项
  • id:当使用可迭代对象或者数组时,index 是当前迭代的序号。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。
<!--
SELECT * FROM USER WHERE age IN (XX,XX)
-->
<select id="findByAge" resultType="user">
    select * from User where age in
  <foreach item="item" index="index" collection="array"
      open="(" separator="," close=")">
        #{item}
  </foreach>
</select>
<!--
insert into user (name,age) values (XX,XX),(XX,XX)
-->
<insert id="insertUser" parameterType="user">
  insert into user (name,age) values 
  <foreach item="item" index="index" collection="list"
      open="(" separator="),(" close=")">
      #{item.name},#{item.age}
  </foreach>
</insert>
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值