Mybatis的动态sql

1. 前置基础: <if> 标签

大多数动态标签都需要结合 <if> 进行条件判断。

java 复制代码
<if test="name != null and name != ''">
    AND name = #{name}
</if>

2. <where> 标签:智能处理 AND/OR 与 WHERE 关键字

作用

用于封装查询条件。

  • 自动插入 WHERE 关键字(如果内部有满足条件的内容)。

  • 智能去除 内部 SQL 语句开头多余的 ANDOR

java 复制代码
<select id="findUser" resultType="User">
    select * from user
    <where>
        <if test="name != null">
            name = #{name}
        </if>
        <if test="age != null">
            AND age = #{age}
        </if>
    </where>
</select>

3. <set> 标签:智能处理逗号与 SET 关键字

作用

用于更新操作。

  • 自动插入 SET 关键字。

  • 智能去除 最后一个字段后面多余的逗号 ,

场景:避免更新语句多余的逗号

java 复制代码
<update id="updateUser">
    update user
    <set>
        <if test="name != null">
            name = #{name},
        </if>
        <if test="age != null">
            age = #{age},
        </if>
        <if test="email != null">
            email = #{email},
        </if>
    </set>
    where id = #{id}
</update>

4. <foreach> 标签:遍历集合(批量操作/IN 查询)

作用

用于遍历数组、List、Map 等集合,通常用于 IN 查询或批量插入。

属性说明

属性 描述
collection 遍历的集合名称(传入的 List/Array/Map 的 Key)
item 当前遍历元素的别名
index 当前索引(List 中是索引,Map 中是 Key)
open 遍历开始拼接的符号(通常是 (
close 遍历结束拼接的符号(通常是 )
separator 元素之间的分隔符(通常是 ,

in条件查询:

java 复制代码
<select id="selectByIds" resultType="User">
    select * from user
    <where>
        id IN
        <foreach collection="list" item="id" open="(" separator="," close=")">
            #{id}
        </foreach>
    </where>
</select>

批量插入

java 复制代码
<insert id="batchInsert">
    insert into user (name, age) values
    <foreach collection="list" item="item" separator=",">
        (#{item.name}, #{item.age})
    </foreach>
</insert>
  • 当遍历 List 或数组时,index 的类型是 int;遍历 Map 时,index 的类型是 Object(与键的类型一致)。
在批量插入中,利用 index 给每个元素加上序号(如生成复合键)
java 复制代码
<insert id="batchInsertWithOrder">
    insert into user_order (user_id, order_seq, product_name) values
    <foreach collection="list" item="item" index="idx" separator=",">
        (#{item.userId}, #{idx}, #{item.productName})
    </foreach>
</insert>

假设传入的 list 包含三个订单项,生成的 SQL 大致为:

java 复制代码
insert into user_order (user_id, order_seq, product_name) values 
(100, 0, '手机'),
(100, 1, '充电器'),
(100, 2, '耳机')
遍历 Map 时,index 取出键(Key)item :表示 Map 中每个键值对的 值(Value)
java 复制代码
<select id="selectByMap" resultType="User">
    select * from user where
    <foreach collection="params" item="value" index="key" separator="AND">
        ${key} = #{value}
    </foreach>
</select>

如果 params 是一个 Map:{"name": "张三", "age": 25},生成的 SQL 是

java 复制代码
select * from user where name = ? AND age = ?

5. <trim> 标签:万能前缀/后缀处理器

<where><set> 本质上是 <trim> 的特殊实现。如果遇到更复杂的拼接需求,可以直接使用 <trim>

属性说明

  • prefix:在 SQL 片段前面加上指定内容。

  • suffix:在 SQL 片段后面加上指定内容。

  • prefixOverrides:去掉 SQL 片段前面指定的多余内容。

  • suffixOverrides:去掉 SQL 片段后面指定的多余内容。

模拟 <where> 标签

java 复制代码
<trim prefix="WHERE" prefixOverrides="AND |OR ">
    ...
</trim>

自定义场景:拼接 values 时去除括号前的逗号

java 复制代码
<trim prefix="(" suffix=")" suffixOverrides=",">
    <if test="name != null">name,</if>
    <if test="age != null">age,</if>
</trim>

6. <choose> (when/otherwise) :类似 Switch 语句

当需要"多选一"的逻辑时使用(只要第一个满足条件的,后面的忽略)。

java 复制代码
<select id="findActiveUser" resultType="User">
    select * from user
    <where>
        <choose>
            <when test="name != null">
                AND name = #{name}
            </when>
            <when test="age != null">
                AND age = #{age}
            </when>
            <otherwise>
                AND status = 'ACTIVE'
            </otherwise>
        </choose>
    </where>
</select>

7. <bind> :绑定变量

用于模糊查询,防止 SQL 注入,或复用变量表达式。

java 复制代码
<select id="selectUser" resultType="User">
    <bind name="pattern" value="'%' + name + '%'"/>
    select * from user where name like #{pattern}
</select>
相关推荐
蓝斯4972 小时前
[原创]《C#高级GDI+实战:从零开发一个流程图》第章:增加贝塞尔曲线,上、下、左、右连接点
java·c#·流程图
前端工作日常3 小时前
我学习到的Java 的 Service 分层:itf 和 impl 到底是什么?
java·后端
都叫我大帅哥3 小时前
Spring @Transactional 注解完全指南
java·spring
Java成神之路-4 小时前
G1 垃圾回收器 :SATB + TAMS核心机制深度解析
java·jvm
前端工作日常4 小时前
我学习到的JIT即时编译与机器码缓存失效
java·后端
带刺的坐椅4 小时前
Solon 的 10 种 HTTP 服务器:改一行依赖,换一个引擎
java·solon·jetty·undertow·mcp-server·htttp
xcLeigh5 小时前
Go入门:变量声明的五种方式详解
java·开发语言·golang
AI大模型-小华5 小时前
Codex 三方充值快速入门指南
java·前端·数据库·chatgpt·ai编程·codex·chatgpt pro
Mark_ZP6 小时前
【锁1】Synchronized vs ReentrantLock区别
java
立心者06 小时前
SpringBoot中使用TOTP实现MFA(多因素认证)
java·spring boot·后端