MyBatis入门之 动态SQL
动态SQL是MyBatis的强大特性之一,极大的简化了我们拼装SQL的操作。
目录复制
if
使用动态SQL最常见的情景是根据条件包含where子句的一部分,比如:
<select id="getPersonByConditionIf" resultMap="myPerson">
select * from person
where age = 20
<if test="name!=null and name != ''">
and name like #{name}
</if>
</select>
这条语句提供了可选的查找文本功能,如果不传入“name”,name所有age=20的person都会返回,如果传入了name,name就会对name一列进行模糊查询并返回对应的person。
如果希望通过id和name两个参数进行可选搜索怎么办呢?只需要加入另一个条件即可。
<select id="getPersonByConditionIf" resultMap="myPerson">
select * from person
where age = 20
<if test="name!=null and name != ''">
and name like #{name}
</if>
<if test="id!=null and id!=''">
and id = #{id}
</if>
</select>
choose(otherwise when)
有时候,我们不想使用所有的条件,而是想从多个条件中选择一个使用。针对这种情况,mybatis提供了choose元素,它有点像Java中的switch语句。choose为switch,when为case,otherwise为default。
select id="getPersonByConditionChoose" resultMap="myPerson">
select * from person
<where>
/* 如果带了id就用id查,如果带了name就用name查询,只会进入其中的一个*/
<choose>
<when test="id != null">
id =#{id}
</when>
<when test="name != null">
name like #{name}
</when>
<otherwise>
age = 18
</otherwise>
</choose>
</where>
</select>
where
当if标签较多时,如果第一个字段值为null,如id = null,如下:
<select id="getPersonByConditionIf" resultMap="myPerson">
select * from person
where
<if test="id!=null">
id = #{id}
</if>
<if test="name!=null and name != ''">
and name = #{name}
</if>
<if test="age!=null and age != ''">
and age = #{age}
</if>
</select>
查询会出现where and 的情况,解决该情况除了将where 修改成 where 1=1之外,
还可以利用这个标签,如果标签返回的内容是以 and 或 or开头的,它就会被剔除。
将其修改为where标签,查看:
<select id="getPersonByConditionIf" resultMap="myPerson">
select * from person
<where>
<if test="id!=null">
id = #{id}
</if>
<if test="name!=null and name != ''">
and name = #{name}
</if>
<if test="age!=null and age != ''">
and age = #{age}
</if>
</where>
</select>
用Where的时候, 把and写在前面
trim
trim字符串截取
<select id="getPersonByConditionTrim" resultMap="myPerson">
<!-- 后面多出的and或者or where标签不能解决
prefix="":前缀:trim标签体中是整个字符串拼串 后的结果。
prefix给拼串后的整个字符串加一个前缀
prefixOverrides="":
前缀覆盖: 去掉整个字符串前面多余的字符
suffix="":后缀
suffix给拼串后的整个字符串加一个后缀
suffixOverrides=""
后缀覆盖:去掉整个字符串后面多余的字符-->
select * from person
<!-- 自定义字符串的截取规则 -->
<trim prefix="where" suffixOverrides="and">
<if test="id != null">
id =#{id} and
</if>
<if test="name!=null and name != ''">
name like #{name} and
</if>
<if test="age != null and age != ''">
age =#{age}
</if>
</trim>
</select>
set
使用 set+if 标签,如果某项为 null 则不进行更新,而是保持数据库原值。
<update id="updatePer">
update person
<set>
<if test="name!=null">
name = #{name}
</if>
<if test="age != null">
age = #{age}
</if>
</set>
where id = #{id}
</update>
foreach
动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候),
foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符。这个元素也不会错误地添加多余的分隔符!
你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象作为集合参数传递给 foreach。当使用可迭代对象或者数组时,index 是当前迭代的序号,item 的值是本次迭代获取到的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。
<select id="getPerByConditionForeach" resultMap="myPerson">
select * from person
<!--
collection:指定要遍历的集合:
list类型的参数会特殊处理封装在map中,map的key就叫list
item:将当前遍历出的元素赋值给指定的变量
separator:每个元素之间的分隔符
open:遍历出所有结果拼接一个开始的字符
close:遍历出所有结果拼接一个结束的字符
index:索引。遍历list的时候是index就是索引,item就是当前值
遍历map的时候index表示的就是map的key,item就是map的值
#{变量名}就能取出变量的值也就是当前遍历出的元素
-->
<foreach collection="ids" item="item_id" separator=","
open="where id in(" close=")">
#{item_id}
</foreach>
</select>
sql
当多种类型的查询语句的查询字段或者查询条件相同时,可以将其定义为常量,方便调用。
<sql id="base_select">
id,name,age
</sql>
<sql id="where_clause">
<trim prefix="where" suffixOverrides="and">
<if test="id != null">
id =#{id} and
</if>
<if test="name!=null and name != ''">
name like #{name} and
</if>
<if test="age != null and age != ''">
age =#{age}
</if>
</trim>
</sql>
include
用于引用定义的常量
<select id="selectAll" resultMap="myPerson">
select
<include refid="base_select" />
from person
<include refid="where_clause"/>
</select>