MyBatis 动态 SQL 标签
1. 分支判断
1.1 if 标签
有时候我们更新操作时,传入的 POJO 类的属性值可能部分是空值,通过 if 语句可以实现属性的动态更新,做到只更新传入的属性列。
<update parameterType="TUser">
update t_user set
<if test="userName != null">
userName = #{userName,jdbcType=VARCHAR},
</if>
<if test="realName != null">
realName = #{realName,jdbcType=VARCHAR},
</if>
<if test="sex != null">
sex = #{sex,jdbcType=TINYINT},
</if>
<if test="mobile != null">
mobile = #{mobile,jdbcType=VARCHAR},
</if>
<if test="email != null">
email = #{email,jdbcType=VARCHAR},
</if>
<if test="note != null">
note = #{note,jdbcType=VARCHAR},
</if>
<if test="position != null">
position_id = #{position.id,jdbcType=INTEGER}
</if>
where id = #{id,jdbcType=INTEGER}
</update>
这么做我们有一个问题就是当 position
属性为 null 时,SQL 语句后面会多出一个逗号,会导致执行失败,此时我们就需要借助 set 标签,或者 trim 标签。
1.2 choose, when, otherwise
前面的 if 标签主要用于单分支判断,如果需要多分支判断使用 choose 标签会更加方便。
<select 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>
满足任何一个 when 标签就跳出 choose,如果所有 when 标签都不满足就执行 otherwise。和编程语言中 if-elseif-else
类似。
2. 辅助标签
2.1 set 标签
set 标签用于前置 set 元素,会动态前置 SET 关键字,同时也会删掉结尾无关的逗号。
在 1.1 中,我们遗留了一个问题,如果最后一个判断返回 false,那么拼接的 SQL 语句就会多出一个逗号,导致语句执行失败,我们可以采用 set 标签来解决这个问题。
<update parameterType="TUser">
update t_user
<set>
<if test="userName != null">
userName = #{userName,jdbcType=VARCHAR},
</if>
<if test="realName != null">
realName = #{realName,jdbcType=VARCHAR},
</if>
<if test="sex != null">
sex = #{sex,jdbcType=TINYINT},
</if>
<if test="mobile != null">
mobile = #{mobile,jdbcType=VARCHAR},
</if>
<if test="email != null">
email = #{email,jdbcType=VARCHAR},
</if>
<if test="note != null">
note = #{note,jdbcType=VARCHAR},
</if>
<if test="position != null">
position_id = #{position.id,jdbcType=INTEGER},
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
2.2 where 标签
where 元素只会在至少有一个子元素的条件返回 SQL 子句的情况下才去插入“WHERE”子句。而且,若语句的开头为“AND”或“OR”,where 元素也会将它们去除。
<select resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from t_user a
<where>
<if test="email != null and email != ''">
and a.email like CONCAT('%', #{email}, '%')
</if>
<if test="sex != null ">
and a.sex = #{sex}
</if>
</where>
</select>
2.3 trim 标签
trim 标签是最大强大的辅助标签,实质上 where 和 set 标签都是 trim 的简写:
where:
<trim prefix="where" prefixOverrides="AND |OR "></trim>
set:
<trim prefix="set" suffixOverrides=","></trim>
如果我们动态插入数据,则也需要去除逗号问题:
<insert >
insert into t_user
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="id != null">
id,
</if>
<if test="userName != null">
userName,
</if>
<if test="realName != null">
realName,
</if>
<if test="sex != null">
sex,
</if>
<if test="mobile != null">
mobile,
</if>
<if test="email != null">
email,
</if>
<if test="note != null">
note,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=INTEGER},
</if>
<if test="userName != null">
#{userName,jdbcType=VARCHAR},
</if>
<if test="realName != null">
#{realName,jdbcType=VARCHAR},
</if>
<if test="sex != null">
#{sex,jdbcType=TINYINT},
</if>
<if test="mobile != null">
#{mobile,jdbcType=VARCHAR},
</if>
<if test="email != null">
#{email,jdbcType=VARCHAR},
</if>
<if test="note != null">
#{note,jdbcType=VARCHAR},
</if>
</trim>
</insert>
3. 循环
<select resultType="domain.blog.Post">
SELECT *
FROM POST P
WHERE ID in
<foreach item="item" index="index" collection="list" open="(" separator="," close=")">
#{item}
</foreach>
</select>
foreach 元素的功能非常强大,它允许你指定一个集合,声明可以在元素体内使用的集合项(item)和索引(index)变量。它也允许你指定开头与结尾的字符串以及在迭代结果之间放置分隔符。这个元素是很智能的,因此它不会偶然地附加多余的分隔符。
注意:你可以将任何可迭代对象(如 List、Set 等)、Map 对象或者数组对象传递给 foreach 作为集合参数。当使用可迭代对象或者数组时,index 是当前迭代的次数,item 的值是本次迭代获取的元素。当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。
foreach 还可用于批量插入的场景中:
<insert >
insert into t_user (userName, realName, sex, mobile, email, note, position_id)
values
<foreach collection="list" separator="," item="user">
(
#{user.userName,jdbcType=VARCHAR},
#{user.realName,jdbcType=VARCHAR},
#{user.sex,jdbcType=TINYINT},
#{user.mobile,jdbcType=VARCHAR},
#{user.email,jdbcType=VARCHAR},
#{user.note,jdbcType=VARCHAR},
#{user.position.id,jdbcType=INTEGER}
)
</foreach>
</insert>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: MyBatis 参数传递
下一篇: 谈谈自己对于 AOP 的了解
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论