Mybatis 动态 SQL
MyBatis 提供了强大的动态 SQL 功能,可以根据条件动态生成 SQL 语句。常用的动态 SQL 标签包括:
if
:条件判断。where
:动态生成WHERE
子句。set
:动态生成SET
子句。trim
:自定义字符串截取。choose
、when
、otherwise
:多条件选择。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
子句,会自动处理前缀 AND
或 OR
。
示例
<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>
-
如果
name
和age
都为空,则不会生成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
标签用于自定义字符串截取,可以替代 where
和 set
标签。
属性
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=","
:移除内容中多余的逗号。
如果 orderByName
为 ASC
,生成的 SQL 为:
SELECT * FROM user ORDER BY name ASC
如果 orderByName
为 ASC
且 orderByAge
为 DESC
,生成的 SQL 为:
SELECT * FROM user ORDER BY name ASC, age DESC
5. choose
、when
、otherwise
标签
choose
标签类似于 Java 中的 switch
语句,when
类似于 case
,otherwise
类似于 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 = ?
-
如果
name
和age
都为空,生成的 SQL 为:SELECT * FROM user WHERE status = 'ACTIVE'
6. foreach
标签
foreach
标签用于遍历集合(如 List
、Set
、数组),通常用于 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
注解
- 如果参数是
List
,collection
的值可以是 参数名称 或默认的list
。 - 如果参数是数组,
collection
的值可以是 参数名称 或默认的array
。 - 如果参数是
Map
,collection
的值是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
:自定义字符串截取。choose
、when
、otherwise
:多条件选择。foreach
:遍历集合。
通过合理使用这些动态 SQL 标签,可以编写出灵活且高效的 SQL 语句,满足各种复杂的查询需求。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具