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>
相关推荐
leonidZhao1 天前
Java 25新特性:模块导入申明
java
weixin_489690021 天前
【IDEA 2025.2.4】 Maven 仅能手动 Reload All Maven Projects 问题解决
java·maven·intellij-idea
雨辰AI1 天前
MySQL 迁移至达梦 DM9 完整改造指南|99% SQL 零改动
java·开发语言·数据库·sql·mysql·政务
golang学习记1 天前
Intellij IDEA 2026重磅更新!开发体验大升级
java·ide·intellij-idea
弹简特1 天前
【Java项目-轻聊】05-AI赋能设计接口文档
java·开发语言
达达爱吃肉1 天前
claude 接入deepseek 运行报错
java·服务器·前端
OctShop大型商城源码1 天前
OctShop对比JAVA商城源码_OctShop大型专业级多用户商城源码
java·开发语言·商城系统·小程序商城·octshop
guslegend1 天前
AGENT.md,Skill与工程规范
java·开发语言·数据库
周末也要写八哥1 天前
C++中单线程方式之无脑上锁
java·开发语言·c++
Reisentyan1 天前
[Advance]GoLang Learn Data Day 4
java·数据库·golang