Mybatis学习笔记-动态sql

动态sql语句,是继结果集映射后,mybatis提供的又一个强大的功能。

以往在应用JDBC编写持久层代码时,由于业务的需要,不同的情况会对应不同的sql,这时,我们只能在Dao层写入大量恶心的if..else以及其他判断语句,这不仅给维护工作带来了极大困难,最重要的是程序猿们看了会非常不爽,以至于不愿意干活-_-!

mybatis利用jstl很好的解决了这个问题:在sqlMapper.xml中定义相关标签来实现sql有的动态拼接。

mybatis提供了八个标签来支持动态sql:

1.if 
2.choose (3.when, 4.otherwise) 
5.trim (6.where, 7.set) 
8.foreach 

下面对这几个标签做简要介绍。

if

该标签(<if test = "jstl_exp"/>)与java中的if语意相同,通过为test属性指定一个jstl表示式即可,可以对多种参数的属性进行判断,以对空值的判断为例:

<select id="dynamicSelectIfOne" 
                 parameterType="Pet" resultType="Pet">
         select * from pet
          <if test="name != null">
             where name = #{name}
         </if>
</select>

这样,若Pet中的name值为null,则在执行sql语句时只执行select * from pet,而不会有后面的where语句。

注意,当用多个条件作为test属性的值时,要用andor连接,而不能用&&或||。

<select id="dynamicSelectIfOne" 
                 parameterType="Pet" resultType="Pet">
         select * from pet
          <if test="name != null and sex = 'm'">
             where name = #{name}
         </if>
</select>

当where语句中有like语句是,在取得变量值的时候就不能用#{}来完成,要用%${paramName}%:

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

2.chose(when,otherwise)
当业务需求中有很多种情况会发生,但同时只会发生一种时,或许使用<if/>可以完成需求,但这不是一种优雅的做法,这种情况应该尽量用<choose/>,<when/>,<otherwise/>来完成:

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

这类似于java中是 case..switch 语句,mybatis依次检查<when/>标签,若有一个复杂test中的条件,则检查终止,生成租后的sql并执行。

3.trime
该标签用于自定义某一标签的行为(略)。

4.where
有时候利用<if/><when/><choose/><otherwise/>没有办法完成既定的需求,例如下面的sql语句:

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>

若所有<if/>都没有匹配,那么最后被执行的sql就变成了SELECT * FROM BLOG WHERE,这显然是一个错误的sql语句,mybatis当然不能允许这样的事情发生,所以mybatis提供了<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>

当没有<if/>被匹配时,最后的sql会变成SELECT * FROM BLOG,当第二个或第三个<if/>被匹配时,mybatis会自动去掉多余的and。这是很方便的,如果有java来实现,绝对是一件让人无比头疼的事。

5.set
和上面的第一个sql一样,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>
  where id=#{id}
</update>

当没有<if/>被匹配时,最终是sql语句就变成了update Author
set where id=#{id}
,这显然不会被执行成功,同where一样,mybatis提供了<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>

同样的,mybatis会自动去除多余的逗号,来生成正确是sql语句。

6.foreach
该标签提供了再sql语句配置时的循环遍历功能,应用起来同样很简单,下面举几个例子来说明一下:
1)参数格式为Map<String,List<POJO>>

 <insert id="dynamicSqlBatchInsert" parameterType="hashmap">
         insert into pet (name,species,sex) values 
         <foreach collection="pets" item="var"  separator="," >
              (#{var.name},#{var.species},#{var.sex})
         </foreach>
 </insert>

2)参数格式为List<POJO>

 <insert id="dynamicSqlBatchInsert" parameterType="list">
         insert into pet (name,species,sex) values 
         <foreach collection="list" item="index"  separator="," >
              (#{name},#{species},#{sex})
         </foreach>
</insert>

3)参数格式为List<String>

 <insert id="dynamicSqlBatchInsert" parameterType="list">
         select <include refid="column"/> from pet where name in 
         <foreach collection="list" item="index"  separator=","  open="(" close = ")">
              (#{index})
         </foreach>
</insert>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值