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 语句,满足各种复杂的查询需求。

浙公网安备 33010602011771号