Mybatis 动态 SQL

MyBatis 提供了强大的动态 SQL 功能,可以根据条件动态生成 SQL 语句。常用的动态 SQL 标签包括:

  • if:条件判断。
  • where:动态生成 WHERE 子句。
  • set:动态生成 SET 子句。
  • trim:自定义字符串截取。
  • choosewhenotherwise:多条件选择。
  • foreach:遍历集合。

1. if 标签

if 标签用于条件判断,如果条件成立,则包含其内部的 SQL 片段。

示例

<select id="selectUserByCondition" resultType="User">
    SELECT * FROM user
    WHERE 1=1
    <if test="name != null">
        AND name = #{name}
    </if>
    <if test="age != null">
        AND age = #{age}
    </if>
</select>
  • test 属性:判断条件,支持 OGNL 表达式。
  • 如果 name 不为空,则添加 AND name = #{name}
  • 如果 age 不为空,则添加 AND age = #{age}

2. where 标签

where 标签用于动态生成 WHERE 子句,会自动处理前缀 ANDOR

示例

<select id="selectUserByCondition" resultType="User">
    SELECT * FROM user
    <where>
        <if test="name != null">
            AND name = #{name}
        </if>
        <if test="age != null">
            AND age = #{age}
        </if>
    </where>
</select>
  • 如果 nameage 都为空,则不会生成 WHERE 子句。

  • 如果 name 不为空,生成的 SQL 为:

    SELECT * FROM user WHERE name = ?
    
  • 如果 name 为空但 age 不为空,生成的 SQL 为:

    SELECT * FROM user WHERE age = ?
    

3. set 标签

set 标签用于动态生成 UPDATE 语句中的 SET 子句,会自动处理后缀逗号。

示例

<update id="updateUser" parameterType="User">
    UPDATE user
    <set>
        <if test="name != null">
            name = #{name},
        </if>
        <if test="age != null">
            age = #{age},
        </if>
    </set>
    WHERE id = #{id}
</update>
  • 如果 name 不为空,生成的 SQL 为:

    UPDATE user SET name = ? WHERE id = ?
    
  • 如果 name 为空但 age 不为空,生成的 SQL 为:

    UPDATE user SET age = ? WHERE id = ?
    

4. trim 标签

trim 标签用于自定义字符串截取,可以替代 whereset 标签。

属性

  • prefix:在内容前添加前缀。
  • suffix:在内容后添加后缀。
  • prefixOverrides:移除内容的前缀。
  • suffixOverrides:移除内容的后缀。

示例1

<select id="selectUserByCondition" resultType="User">
    SELECT * FROM user
    <trim prefix="WHERE" prefixOverrides="AND |OR ">
        <if test="name != null">
            AND name = #{name}
        </if>
        <if test="age != null">
            AND age = #{age}
        </if>
    </trim>
</select>
  • 如果 name 不为空,生成的 SQL 为:

    SELECT * FROM user WHERE name = ?
    
  • 如果 name 为空但 age 不为空,生成的 SQL 为:

    SELECT * FROM user WHERE age = ?
    

示例2

<select id="selectUserByCondition" resultType="User">
    SELECT * FROM user
    <trim prefix="ORDER BY" suffixOverrides=",">
        <if test="orderByName != null">
            name ${orderByName},
        </if>
        <if test="orderByAge != null">
            age ${orderByAge},
        </if>
    </trim>
</select>
  • prefix="ORDER BY":在内容前添加 ORDER BY
  • suffixOverrides=",":移除内容中多余的逗号。

如果 orderByNameASC,生成的 SQL 为:

SELECT * FROM user ORDER BY name ASC

如果 orderByNameASCorderByAgeDESC,生成的 SQL 为:

SELECT * FROM user ORDER BY name ASC, age DESC

5. choosewhenotherwise 标签

choose 标签类似于 Java 中的 switch 语句,when 类似于 caseotherwise 类似于 default

示例

<select id="selectUserByCondition" 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>
  • 如果 name 不为空,生成的 SQL 为:

    SELECT * FROM user WHERE name = ?
    
  • 如果 name 为空但 age 不为空,生成的 SQL 为:

    SELECT * FROM user WHERE age = ?
    
  • 如果 nameage 都为空,生成的 SQL 为:

    SELECT * FROM user WHERE status = 'ACTIVE'
    

6. foreach 标签

foreach 标签用于遍历集合(如 ListSet、数组),通常用于 IN 子句。

属性

  • collection:集合的名称(要区分是否在mapper接口中使用了@param注解)。
  • item:遍历时的每个元素。
  • index:遍历时的索引(可选)。
  • open:在内容前添加的前缀。
  • close:在内容后添加的后缀。
  • separator:元素之间的分隔符。

示例1

Mapper 接口

public interface UserMapper {
    List<User> selectUsersByIds(@Param("idList") List<Integer> ids);
}
  • @Param("idList"):指定参数名称为 idList

Mapper xml 文件

<select id="selectUsersByIds" resultType="User">
    SELECT * FROM user
    WHERE id IN
    <foreach collection="idList" item="id" open="(" separator="," close=")">
        #{id}
    </foreach>
</select>

collection="idList":因为 Mapper 接口中使用了 @Param 注解指定参数为 idList

-- 如果 ids 是 [1, 2, 3],生成的 SQL 为:
SELECT * FROM user WHERE id IN (1, 2, 3)

示例2

Mapper 接口

public interface UserMapper {
    List<User> selectUsersByIds(List<Integer> ids);
}
  • 参数是一个 List,没有使用 @Param 注解。

Mapper xml 文件

<select id="selectUsersByIds" resultType="User">
    SELECT * FROM user
    WHERE id IN
    <foreach collection="list" item="id" open="(" separator="," close=")">
        #{id}
    </foreach>
</select>

collection="list"collection="ids":当不使用 @param 注解时 参数名 或 集合类型 都可以

-- 如果 ids 是 `[1, 2, 3]`,生成的 SQL 为:
SELECT * FROM user WHERE id IN (1, 2, 3)

总结

1. 不使用 @Param 注解

  • 如果参数是 Listcollection 的值可以是 参数名称 或默认的 list
  • 如果参数是数组,collection 的值可以是 参数名称 或默认的 array
  • 如果参数是 Mapcollection 的值是 Map 中的 键名

2. 使用 @Param 注解

  • collection 的值是 @Param 注解中指定的名称。

7. 抽取sql重复片段

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapper接口全限定名">
  
    <sql id="sql_count">
            select count(*)
    </sql>
    
    <select id="selectCount" resultType="com.iot.site.module.quote.entity.Quote">
    	<include refid = "sql_count"/> from site_quote
	</select>
  
</mapper>

综合示例

场景

根据条件查询用户:

  • 如果 name 不为空,按 name 查询。
  • 如果 age 不为空,按 age 查询。
  • 如果 ids 不为空,按 id 列表查询。
  • 如果所有条件都为空,查询状态为 ACTIVE 的用户。

Mapper XML 文件

<select id="selectUserByCondition" resultType="User">
    SELECT * FROM user
    <where>
        <choose>
            <when test="name != null">
                AND name = #{name}
            </when>
            <when test="age != null">
                AND age = #{age}
            </when>
            <when test="ids != null and ids.size() > 0">
                AND id IN
                <foreach collection="ids" item="id" open="(" separator="," close=")">
                    #{id}
                </foreach>
            </when>
            <otherwise>
                AND status = 'ACTIVE'
            </otherwise>
        </choose>
    </where>
</select>

总结

  • if:条件判断。
  • where:动态生成 WHERE 子句。
  • set:动态生成 SET 子句。
  • trim:自定义字符串截取。
  • choosewhenotherwise:多条件选择。
  • foreach:遍历集合。

通过合理使用这些动态 SQL 标签,可以编写出灵活且高效的 SQL 语句,满足各种复杂的查询需求。

posted @   CyrusHuang  阅读(30)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示