MyBatis 动态 SQL 标签

发布于 2023-10-18 19:45:01 字数 5959 浏览 27 评论 0

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

Oo萌小芽oO

暂无简介

0 文章
0 评论
22 人气
更多

推荐作者

内心激荡

文章 0 评论 0

JSmiles

文章 0 评论 0

左秋

文章 0 评论 0

迪街小绵羊

文章 0 评论 0

瞳孔里扚悲伤

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文