首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【MyBatis】动态SQL,<if>、<trim>、<where>、<set>、<foreach>、<include>

【MyBatis】动态SQL,<if>、<trim>、<where>、<set>、<foreach>、<include>

作者头像
椰椰椰耶
发布2025-07-21 09:03:16
发布2025-07-21 09:03:16
26300
代码可运行
举报
文章被收录于专栏:学习学习
运行总次数:0
代码可运行

<if> 标签

在用户注册的时候,可能会有这样一个问题,如下:

image.png
image.png

注册分为两种字段:

  • 必填字段
  • 非必填字段 如果在添加用户的时候有不确定的字段传入,程序应用如何实现呢?

这个时候就需要使用动态标签来判断了,比如添加的时候性别 gender 为非必填字段,具体实现如下:

接口定义:p

代码语言:javascript
代码运行次数:0
运行
复制
Integer insertUserByCondition(UserInfo userInfo);

xml

Mapper.xml 实现

代码语言:javascript
代码运行次数:0
运行
复制
<insert id="insertUserByCondition">  
    insert into userinfo (username, 'password', age, <if test="gender != null">gender,</if> phone)  
    value (#{username}, #{age}, <if test="gender != null">#{gender},</if>> #{phone})  
</insert>

注解

此方法不推荐


把上面的 SQL(包括标签),使用 <script></script> 括起来就行

代码语言:javascript
代码运行次数:0
运行
复制

<trim>标签

之前的插入用户功能,只是有一个 gender 字段可能是选填项,如果有多个字段,一般考虑使用标签结合标签,对多个字段都采取动态生成的方式。

标签中有如下属性:

  • prefix:表示整个语句块以 prefix 的值作为前提
  • suffix:表示整个语句块以 suffix 的值作为后缀
  • prefixOverrides:表示整个语句块要去除掉的前缀
  • suffixOverrides:表示整个语句块要去除掉的后缀

调整 Mapper.xml 的插入语句为:

代码语言:javascript
代码运行次数:0
运行
复制
<insert id="insertUserByTrim">  
    insert into userinfo  
    <trim prefix="(" suffix=")" suffixOverrides=",">  
        <if test="username != null">  
            username,  
        </if>>  
        <if test="password != null">  
            password,  
        </if>  
        <if test="age != null">  
            age,  
        </if>  
        <if test="gender != null">  
            gender,  
        </if>  
        <if test="phone != null">  
            phone,  
        </if>  
    </trim>  
    values  
    <trim prefix="(" suffix=")" suffixOverrides=",">  
        <if test="username != null">  
            #{username},  
        </if>>  
        <if test="password != null">  
            #{password},  
        </if>  
        <if test="age != null">  
            #{age},  
        </if>  
        <if test="gender != null">  
            #{gender},  
        </if>  
        <if test="phone != null">  
            #{phone},  
        </if>  
    </trim>  
</insert>

在以上 SQL 动态解析时,会将第一个部分做如下处理:

  • 基于 prefix 配置,开始部分加上 (
  • 基于 suffix 配置,结束部分加上 )
  • 多个组织的语句都以 , 结尾,在最后拼接好的字符串还会以 , 结尾,会基于 suffixOverrides 配置去掉最后一个 ,
  • 注意 <if test+"username != null"> 中的 username 是传入对象的属性

<where>标签

看下面的场景,系统会根据我们筛选条件,动态组装 where 条件

image.png
image.png

这种如何实现呢?接下来我们看代码实现

需求:传入的用户对象,根据属性做 where 条件查询,用户对象中属性不为 null 的,都为查询条件

  • usernamea,则查询条件为 where username=“a”

原有 SQL

代码语言:javascript
代码运行次数:0
运行
复制
select * from userinfo where age = 18 and gender = 1

xml

接口定义:

代码语言:javascript
代码运行次数:0
运行
复制
List<UserInfo> queryByWhere();
代码语言:javascript
代码运行次数:0
运行
复制
<select id="selectUserByWhere" resultType="com.glg.mybatis.model.UserInfo">  
    select id, username, age, gender from userinfo  
    <where>  
        <if test="age != null">  
            and age = #{age}  
        </if>  
        <if test="gender != null">  
            and gender = #{gender}  
        </if>  
    </where>  
</select>
  • <where> 只会在子元素有内容的情况下才插入 where 自居,而且会自动去除句子开头的 andor
  • 以上标签也可以使用 <trim prefix="where" prefixOverrides="and"> 替换,但是此种情况下,当子元素都没有内容时,where 关键字也会保留

<set>标签

需求:根据传入的用户对象属性来更新用户数据,可以使用标签来指定动态内容

接口定义:根据传入的用户 id 属性,修改其他不为 null 的属性

代码语言:javascript
代码运行次数:0
运行
复制
Integer updateUserBySet();

Mapper.xml

代码语言:javascript
代码运行次数:0
运行
复制
<update id="updateUserBySet">  
    update userinfo  
    <set>  
        <if test="username != null">  
            username = #{username}  
        </if>  
        <if test="age != null">  
            age = #{age}  
        </if>  
    </set>  
    where id = #{id}  
</update>
  • <set>:动态的在 SQL 语句中插入 set 关键字,并会删除掉额外的逗号(用于 update 语句中),以上标签也可以使用 <trim prefix="set" suffixOverrides=","> 替换

<foreach>标签

对集合进行遍历时可以用该标签,标签有如下属性

  • collection:绑定方法参数中的集合,如 ListSetMap 或数组对象
  • item:遍历时的每一个对象
  • open:语句块开头的字符串
  • close:语句块结束的字符串
  • separator:每次遍历之间间隔的字符串

需求:根据多个 userid,删除用户数据

接口方法:

代码语言:javascript
代码运行次数:0
运行
复制
void deleteBySet(List<Integer> ids);

ArticleMapper.xml 中新增删除 SQL

代码语言:javascript
代码运行次数:0
运行
复制
<delete id="deleteUserBySet">  
    delete from userinfo where id in  
    <foreach collection="ids" item="id" separator="," open="(" close=")">  
        #{id}  
    </foreach>  
</delete>

<include>标签

问题分析:

  • xml 映射文件中配置的 SQL,有时可能会存在很多重复的片段,此时就会存在很多冗余的代码
image.png|404
image.png|404

我们可以对重复的代码片段进行抽取,将其通过 <sql> 标签封装到一个 SQL 片段,然后再通过 <include> 标签进行引用

  • <sql>:定义可重复用的 SQL 片段
  • <include>:通过属性 refid,指定包含的 SQL 片段
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-07-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • <if> 标签
    • xml
    • 注解
  • <trim>标签
  • <where>标签
    • xml
  • <set>标签
  • <foreach>标签
  • <include>标签
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档