MyBatis 动态 SQL

动态 SQL

动态 SQL 是 MyBatis 的强大特性之一。动态 SQL 可以根据运行时提供的条件,包括 参数值、逻辑判断、循环 等,动态生成SQL语句的各个部分的具体内容。

对动态SQL的学习主要是学习几个重要的标签,下面我们详细介绍:

1、<if> 标签

<if> 标签的作用是根据条件判断是否生成相应的 SQL 片段或语句。

例:根据可选参数插入用户信息

java 复制代码
    <insert id="insert2" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
        insert into userinfo(username, password
        <if test="photo != null">
            ,photo
        </if>
        ) values (
        #{username},
        #{password}
        <if test="photo != null">
            ,#{photo}
        </if>
        )
    </insert>

: test 中的 字段名,是传入对象中的 属性,不是数据库字段。


2、<trim> 标签

虽然上面的 <if> 标签可以实现一些动态 SQL,但是如果所有的参数都是可选参数的情况下,只使用 <if> 标签就可能会出错。例如:

java 复制代码
    <insert id="insert2" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
        insert into userinfo(
        <if test="username != null">
            username
        </if>
        <if test="password != null">
            ,password
        </if>
        ) values (
        <if test="username != null">
            #{username}
        </if>
        <if test="password != null">
            ,#{password}
        </if>
        )
    </insert>

上述这种情况下,如果只传入 username 参数,那么最终拼接的 SQL 语句为:insert into userinfo(,password)......显然,这是一个错误的 SQL 语句。

此时我们可以使用 <trim> 标签结合 <if> 标签,解决上述问题:

trim 标签中的重要属性:

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

使用 <trim> 标签解决上述问题:

java 复制代码
    <insert id="insert2" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
        insert into userinfo
        <trim prefix="(" suffix=")" prefixOverrides=",">
            <if test="username != null">
                username
            </if>
            <if test="password != null">
                ,password
            </if>
        </trim>
        values
        <trim prefix="(" suffix=")" prefixOverrides=",">
            <if test="username != null">
                #{username}
            </if>
            <if test="password != null">
                ,#{password}
            </if>
        </trim>
    </insert>

3、<where> 标签

  1. <where> 标签内部的条件会根据实际情况自动生成 where 子句。
  2. <where>标签会自动去除最前面的"and"和"or"关键字。
  3. 根据以上特性,<where>标签也可以使用 <trim prefix="where" prefixOverrides="and"> 或 <trim prefix="where" prefixOverrides="or">替换。

例:根据可选参数查询用户信息

java 复制代码
    <select id="getUserInfoByWhere" resultType="com.example.demo.model.UserInfo">
        select * from userinfo
        <where>
            <if test="id > 0">
                id=#{id}
            </if>
            <if test="photo != null">
                and photo=#{photo}
            </if>
        </where>
    </select>


4、<set> 标签

  1. <set> 标签内部的条件会根据实际情况自动生成 set 子句。
  2. <set>标签会自动去除最后面的,
  3. 根据以上特性,<set> 标签也可以使⽤ <trim prefix="set" suffixOverrides=","> 替换

例:设置可选参数更新用户信息

java 复制代码
    <update id="updateBySet">
        update userinfo
        <set>
            password=#{password},
            <if test="username != null">
                username=#{username},
            </if>
            <if test="photo != null">
                photo=#{photo}
            </if>
        </set>
        where id=#{id}
    </update>

5、<foreach> 标签

<foreach> 标签用于在 SQL 语句中循环遍历集合或数组,并将其元素应用到 SQL 的特定部分。

下面是 <foreach> 标签中的重要属性:

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

例如根据用户 id 批量删除用户信息:

接口:

java 复制代码
int deleteByIds(List<Integer> ids);

xml 实现:

java 复制代码
    <delete id="deleteByIds">
        delete from userinfo
        where id in
        <foreach collection="ids" open="(" close=")" item="id" separator=",">
            #{id}
        </foreach>
    </delete>
相关推荐
逢生博客13 分钟前
使用 Python 项目管理工具 uv 快速创建 MCP 服务(Cherry Studio、Trae 添加 MCP 服务)
python·sqlite·uv·deepseek·trae·cherry studio·mcp服务
堕落似梦19 分钟前
Pydantic增强SQLALchemy序列化(FastAPI直接输出SQLALchemy查询集)
python
獨枭25 分钟前
SQL Server 2019 安装与配置详细教程
sql·sqlserver
啊松同学38 分钟前
【Mybatis】MyBatisPlus的saveBatch真的是批量插入吗?深度解析与性能优化
java·后端·性能优化·mybatis
阿里小阿希1 小时前
解决 Spring Boot + MyBatis 项目迁移到 PostgreSQL 后的数据类型不匹配问题
spring boot·postgresql·mybatis
坐吃山猪1 小时前
Python-Agent调用多个Server-FastAPI版本
开发语言·python·fastapi
Bruce-li__2 小时前
使用Django REST Framework快速开发API接口
python·django·sqlite
小兜全糖(xdqt)2 小时前
python 脚本引用django中的数据库model
python·django
Arenaschi2 小时前
SQLite 是什么?
开发语言·网络·python·网络协议·tcp/ip
纪元A梦2 小时前
华为OD机试真题——推荐多样性(2025A卷:200分)Java/python/JavaScript/C++/C语言/GO六种最佳实现
java·javascript·c++·python·华为od·go·华为od机试题