【热】Mybaits-动态sql一篇入门

Mybaits

动态sql

MyBatis 采用功能强大的基于 OGNL 的表达式来消除其他元素。

动态传递参数有两种方式:

#{} 占位符
  • 为参数占位符 ?,即sql 预编译
  • 变量替换后,#{} 对应的变量自动加上单引号 ‘’
  • 能防止sql 注入
// 1
select * from t_user where uid=#{uid}
// 2
select * from t_user where uid= ?
// 3
select * from t_user where uid= '1'
${} 占位符

只是简单的字符串替换

  • ${} 为字符串替换,即 sql 拼接
  • 变量替换后,${} 对应的变量不会加上单引号 ‘’
  • 不能防止sql 注入
// 1 这里提前加上了'',
select * from t_user where uid= '${uid}'
// 2
select * from t_user where uid= '1'
// 3
select * from t_user where uid= '1'

  • if
  • choose when otherwise
  • where
  • set
  • trim
  • foreach

if

不支持 && 所以用 and or ||

条件对应
eq==
neq!=
gt>
gte>=
lt<(会报错)原因:不能包含<
lte<=(会报错)原因:不能包含<
<select id="findActiveBlogWithTitleLike" resultType="Blog">
  SELECT * FROM BLOG 
  WHERE state = `ACTIVE`
  <if test="title != null">
    AND title like #{title}
  </if>
</select>

// 判断是否为空
<if test="username != null and username != ''">

1 如果参数为数字类型的时候没有特俗需求的情况只需要判断是否为null即可。
<if test="id != null"></if>
2 如果为字符串类型

2.1 如果不需要过滤空串的情况 仅仅判断null即可
<if test="username != null"></if>

2.2 如果需要过滤空串,添加空串判断即可,不支持 && 所以这里用 and  or  || 来做逻辑与或的判断 
<if test="username != null and '' != username"></if>

2.3 如果判断字符串是否已某个特俗字符开头,结尾等。直接调用String的对应方法即可
<if test="username != null and username.indexOf('ji') == 0"> </if> <!-- 是否以什么开头 -->
<if test="username != null and username.indexOf('ji') >= 0"> </if> <!-- 是否包含某字符 -->
<if test="username != null and username.lastIndexOf('ji') > 0"></if>  <!-- 是否以什么结尾 -->

2.4 是否是某个特定字符串,某些业务有此需要。
<if test="username != null and 'hello' == username"></if>
<if test="username != null and 'hello' eq username"></if>
参数类型为非字符串类型的时候就需要写成 
<if test="username != null and 'hello'.toString() == username.toString()"></if>

choose when otherwise

if标签是与(and)的关系,而 choose 是或(or)的关系

等价于

if...{  
....  
}else if(...){  
...  
}else{  
....  
}  
<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>

where

where 元素知道只有在一个以上的if/when…条件有值的情况下才去插入"WHERE"子句。而且,若最后的内容是"AND"或"OR"开头的,where 元素也知道如何将他们去除。

出现的原因是为了解决一些垃圾问题

<select id="findActiveBlogLike" resultType="Blog">
    SELECT * FROM BLOG 
    WHERE  // 如果if没有匹配,那么sql语句会报错。
    <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>


// 如果这些条件没有一个能匹配上将会怎样?最终这条 SQL 会变成这样:
SELECT * FROM BLOG
WHERE

这会导致查询失败。如果仅仅第二个条件匹配又会怎样?这条 SQL 最终会是这样:
SELECT * FROM BLOG
WHERE
AND title like 'someTitle'

例子

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


<where>
    <choose>
        <when test="studentName!=null and studentName!='' ">     
                    ST.STUDENT_NAME LIKE CONCAT(CONCAT('%', #{studentName}),'%')      
        </when>
        <when test="studentSex!= null and studentSex!= '' ">     
                    AND ST.STUDENT_SEX = #{studentSex}      
        </when>
        <when test="studentBirthday!=null">     
                AND ST.STUDENT_BIRTHDAY = #{studentBirthday}      
        </when>
        <when test="classEntity!=null and classEntity.classID !=null and classEntity.classID!='' ">     
                AND ST.CLASS_ID = #{classEntity.classID}      
        </when>
        <otherwise>

        </otherwise>
    </choose>
</where>

也可以用trim替代

  • prefixOverrides 属性会忽略通过管道分隔的文本序列(空格是必要的)
// prefixOverrides 属性会忽略通过管道分隔的文本序列(空格是必要的),而又一次附加了前缀中的值。
<trim prefix="WHERE" prefixOverrides="AND |OR ">
  ... 
</trim>

set

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>

也可以用trim替代

// suffixOverrides忽略的是后缀中的值,而又一次附加了前缀中的值。
<trim prefix="SET" suffixOverrides=",">
  ...
</trim>

foreach

对一个集合进行遍历,通常是在构建 IN 条件语句的时候。

属性描述
item集合中元素迭代时的别名,该参数为必选。
index在list和数组中,index是元素的序号,在map中,index是元素的key,该参数可选
openforeach代码的开始符号,一般是(和close=")"合用。常用在in(),values()时。该参数可选
separator元素之间的分隔符,例如在in()的时候,separator=","会自动在元素中间用“,“隔开,避免手动输入逗号导致sql错误,如in(1,2,)这样。该参数可选。
closeforeach代码的关闭符号,一般是)和open="("合用。常用在in(),values()时。该参数可选。
collection要做foreach的对象,作为入参时,List对象默认用"list"代替作为键,数组对象有"array"代替作为键,Map对象没有默认的键。当然在作为入参时可以使用@Param(“keyName”)来设置键,设置keyName后,list,array将会失效。
  • 在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,但是在不同情况下,该属性的值是不一样的,主要有一下3种情况:

    • 如果传入的是单参数且参数类型是一个List(集合)的时候,collection属性值为list .
    List<String> entitys;
    <foreach item="item" index="index" collection="list" open="(" separator="," close=")">
        #{item}
    </foreach>
    
    • 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array .
    int[] ids = new int[] {1,3,6,9};
    <foreach item="item" index="index" collection="array" open="(" separator="," close=")">
        #{item}
    </foreach>
    
    • 如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map,实际上如果你在传入参数的时候,在MyBatis里面也是会把它封装成一个Map的,map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key.
    List ids = new ArrayList();
    ids.add(1);
    ids.add(2);
    ids.add(3);
    ids.add(6);
    ids.add(7);
    ids.add(9);
    Map params = new HashMap();
    params.put("ids", ids);
    params.put("title", "中国");
    
    select * from t_blog where title like "%"#{title}"%" and id in
    <foreach item="item" index="index" collection="ids" open="(" separator="," close=")">
        #{item}
    </foreach>
    
<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>

trim

去除或者添加特定的前缀或者后缀

属性描述
prefix给sql语句拼接的前缀
suffix给sql语句拼接的后缀
prefixOverrides去除sql语句前面的关键字或者字符,该关键字或者字符由prefixOverrides属性指定,假设该属性指定为"AND",当sql语句的开头为"AND",trim标签将会去除该"AND"
suffixOverrides去除sql语句后面的关键字或者字符,该关键字或者字符由suffixOverrides属性指定
使用trim标签去除多余的and/or关键字

使用管道符时,管道符前面的空格必须带上。

<trim prefix="WHERE" prefixOverrides="AND |OR ">
  ... 
</trim>
使用trim标签去除多余的逗号
<trim prefix="SET" suffixOverrides=",">
  ...
</trim>

参考文章

MyBatis中#{}和${}的区别

MyBatis Mapper XML 文件 的学习详解

mybatis trim标签的使用

mybatis之foreach用法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值