Mybatis的动态sql

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

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

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

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

作用

用于封装查询条件。

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

  • 智能去除 内部 SQL 语句开头多余的 AND 或 OR。

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>
相关推荐
松仔log12 分钟前
Kotlin中级——callbackFlow
java·前端·kotlin
知守观1 小时前
同一个团队两套分包:DDD 四层落地后,domain 层最大的类还是 5885 行
java·后端·领域驱动设计
文丑颜不良啊1 小时前
LeetCode2541~2560题目解析
java·leetcode
瑞雪兆丰年兮1 小时前
JavaWeb-day11-SpringBootWeb案例(文件上传)
java·运维·服务器·javaweb·oss
Highcharts.js2 小时前
Highcharts智能数据分析平台Orbit 多语言配置技术文档
java·前端·javascript·highcharts·orbit·智能数据分析·设置文档
Rain的Java大神之路2 小时前
设计一套生产级 API 接口:从契约、安全、幂等到限流,我踩过的坑都在这了
java·后端·面试
SimonKing2 小时前
零配置也能白嫖前沿大模型!dsh-our-free-model插件真香警告
java·后端·程序员
nice_lcj5202 小时前
【从零理解 Spring AI · 15】让检索更准:先宽召回,再精排序
java·后端·rag·spring ai·ai应用开发·检索优化·重排序
杨凯凡3 小时前
Spring Boot 链路追踪实战:Micrometer、TraceId 与异步线程上下文传播
java·spring boot·后端
计算机毕设定制辅导-无忧学长3 小时前
《基于Spring Boot的迷游哈游戏综合服务平台的开发》
java·vue.js·spring boot·mysql·迷游哈游戏综合服务平台