一、介绍
动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。
二、具体使用
1.if语句
使用动态SQL最常见场景是根据条件包含where子句的一部分
<select id="query" parameterType="user" resultType="user">
select
*
from t_user
where
1=1
<if test="username!=null">
and username=#{username}
</if>
<if test="address!=null">
and address like #{address}
</if>
<if test="gender!=null">
and gender=#{gender}
</if>
</select>
测试
2. where语句
我们在写SQL语句的where部分的时候是为了保证SQL语句的语法正确,所以我们会加上1=1的表达式,如果我们不想这么写的话可以使用 < where> 标签来替代。
<select id="query" parameterType="user" resultType="user">
select
*
from t_user
<where>
<if test="username!=null">
and username=#{username}
</if>
<if test="address!=null">
and address like #{address}
</if>
<if test="gender!=null">
and gender=#{gender}
</if>
</where>
</select>
3.choose、when、otherwise
有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个。针对这种情况,MyBatis提供了choose元素,它有点像Java中的语句。
<select id="queryChoose" parameterType="user" resultType="user">
select
*
from t_user
where 1=1
<choose>
<when test="username!=null">
and username=#{username}
</when>
<when test="address!=null">
and address like #{address}
</when>
<otherwise>
order by id desc
</otherwise>
</choose>
</select>
4.set语句
当我们要实现动态更新的时候会因为 ,的问题而造成非常麻烦的后果,这时我们可以通过< set >标签来动态管理
<update id="updateUser" parameterType="user" >
update
t_user
<set>
<if test="username!=null">
username=#{username},
</if>
<if test="address!=null">
address=#{address},
</if>
<if test="gender!=null">
gender=#{gender},
</if>
</set>
where id=#{ id }
</update>
5.trim语句
trim标记是一个格式化的标记。可以完成set或者where标记的功能
属性 | 说明 |
---|---|
prefix | 前缀 |
prefixOverrides | 去掉第一个指定内容 |
suffix | 后缀 |
suffixOverrides | 去掉最后一个指定内容 |
替代< where >标签
<select id="queryWhere" parameterType="user" resultType="user">
select
*
from t_user
<trim prefix="where" prefixOverrides="AND|OR">
<if test="username!=null">
and username=#{username}
</if>
<if test="address!=null">
and address=#{address}
</if>
<if test="gender!=null">
and gender=#{gender}
</if>
</trim>
</select>
替代< set >标签
<update id="updateSet" parameterType="user">
update
t_user
<trim prefix="set" prefixOverrides=",">
<if test="username!=null">
,username=#{username}
</if>
<if test="address!=null">
,address=#{address}
</if>
<if test="gender!=null">
,gender=#{gender}
</if>
</trim>
where id=#{id}
</update>
<update id="updateSetTwo" parameterType="user">
update
t_user
<trim prefix="set" suffixOverrides=",">
<if test="username!=null">
username=#{username},
</if>
<if test="address!=null">
address=#{address},
</if>
<if test="gender!=null">
gender=#{gender},
</if>
</trim>
where id=#{id}
</update>
6.foreach
动态SQL的另一个常见使用场景是对集合进行遍历
属性 | 说明 |
---|---|
collection | collection属性的值有三个分别是list、array、map三种 |
open | 前缀 |
close | 后缀 |
separator | 分隔符,表示迭代时每个元素之间以什么分隔 |
item | 表示在迭代过程中每一个元素的别名 |
index | 用一个变量名表示当前循环的索引位置 |
<select id="queryUserById" resultType="user">
select
*
from t_user
<where>
<if test="ids!=null">
id in
<foreach collection="ids" open="(" close=")" item="id" separator=",">
#{id}
</foreach>
</if>
</where>
</select>
接口定义
7.bind语句
bind元素允许你在OGNL表达式以外创建一个变量,并将其绑定到当前的上下文
<select id="selectBlogsLike" resultType="Blog">
<bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
SELECT * FROM BLOG
WHERE title LIKE #{pattern}
</select>
8.SQL代码片段
可重复使用的SQL语句代码片段
<sql id="BaseSQL">
id,username,address,gender
</sql>
<select id="querySQL" parameterType="user" resultType="user">
select
<include refid="BaseSQL"></include>
from t_user
where
1=1
<if test="username!=null">
and username=#{username}
</if>
<if test="address!=null">
and address=#{address}
</if>
<if test="gender!=null">
and gender=#{gender}
</if>
</select>