恐怖解谜密室逃脱
109.73M · 2026-03-09
核心主题:MyBatis<trim>标签基本使用、动态SQL拼接、WHERE条件优化
适用场景:动态查询条件构建、批量更新语句、灵活的SQL片段组装
一句话总结:<trim>标签智能处理SQL前后缀和多余关键字,让动态SQL更优雅、更可靠
<trim>标签通过配置前缀、后缀、去除关键字,自动处理动态SQ 的拼接逻辑
核心逻辑:根据标签内容是否为空,智能添加或删除指定的SQL片段
核心价值:替代手动拼接SQL,避免语法错误(如多余的AND、OR、SET),提升代码可维护性
<!-- Maven依赖(Spring Boot项目默认包含) -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.3.0</version>
</dependency>
<!-- 或使用 MyBatis Plus(兼容原生 MyBatis) -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3</version>
</dependency>
// 实体类
@Data
public class User {
private Long id;
private String username;
private String email;
private Integer age;
private Integer status;
}
<!-- Mapper XML文件 -->
<mapper namespace="com.example.mapper.UserMapper">
<!-- 基础结果映射 -->
<resultMap id="BaseResultMap" type="com.example.entity.User">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="email" property="email"/>
<result column="age" property="age"/>
<result column="status" property="status"/>
</resultMap>
<!-- 动态查询:使用 trim 处理 WHERE 条件 -->
<select id="selectByCondition" parameterType="com.example.entity.User" resultMap="BaseResultMap">
SELECT * FROM user
<trim prefix="WHERE" prefixOverrides="AND|OR">
<!-- 如果 username 不为空,添加条件 -->
<if test="username != null and username != ''">
AND username LIKE CONCAT('%', #{username}, '%')
</if>
<!-- 如果 email 不为空,添加条件 -->
<if test="email != null and email != ''">
AND email = #{email}
</if>
<!-- 如果 age 不为空,添加条件 -->
<if test="age != null">
AND age > #{age}
</if>
<!-- 如果status不为空,添加条件 -->
<if test="status != null">
AND status = #{status}
</if>
</trim>
ORDER BY id DESC
</select>
</mapper>
// Mapper接口
@Mapper
public interface UserMapper {
List<User> selectByCondition(@Param("user") User user);
}
// 测试代码
@SpringBootTest
public class UserMapperTest {
@Autowired
private UserMapper userMapper;
@Test
public void testSelectByCondition() {
// 测试1:只有 username 条件
User condition1 = new User();
condition1.setUsername("john");
List<User> result1 = userMapper.selectByCondition(condition1);
System.out.println("查询结果1: " + result1.size());
// 测试2:多个条件组合
User condition2 = new User();
condition2.setUsername("alice");
condition2.setAge(18);
condition2.setStatus(1);
List<User> result2 = userMapper.selectByCondition(condition2);
System.out.println("查询结果2: " + result2.size());
// 测试3:无条件(返回所有)
User condition3 = new User();
List<User> result3 = userMapper.selectByCondition(condition3);
System.out.println("查询结果3: " + result3.size());
}
}
生成的SQL示例:
-- 测试1:只有 username 条件(自动去除开头的 AND)
SELECT * FROM user
WHERE username LIKE CONCAT('%', 'john', '%')
ORDER BY id DESC
-- 测试2:多个条件组合
SELECT * FROM user
WHERE username LIKE CONCAT('%', 'alice', '%')
AND age > 18
AND status = 1
ORDER BY id DESC
-- 测试3:无条件(不生成 WHERE 子句)
SELECT * FROM user
ORDER BY id DESC
<!-- 动态更新:使用 trim 处理 SET 关键字 -->
<update id="updateSelective" parameterType="com.example.entity.User">
UPDATE user
<trim prefix="SET" suffixOverrides=",">
<if test="username != null and username != ''">
username = #{username},
</if>
<if test="email != null and email != ''">
email = #{email},
</if>
<if test="age != null">
age = #{age},
</if>
<if test="status != null">
status = #{status},
</if>
</trim>
WHERE id = #{id}
</update>
// 测试代码
@Test
public void testUpdateSelective() {
// 准备数据
User user = new User();
user.setId(1L);
user.setUsername("updated_user");
user.setEmail("new@example.com");
// 只更新 username 和 email,age 和 status 保持不变
int rows = userMapper.updateSelective(user);
System.out.println("更新行数:" + rows);
}
生成的SQL示例:
-- 只更新非空字段(自动去除末尾的逗号)
UPDATE user
SET username = 'updated_user',
email = 'new@example.com'
WHERE id = 1
<!-- 1. prefix:在trim标签内容前添加的前缀 -->
<trim prefix="WHERE">
<!-- 内容 -->
</trim>
<!-- 生成:WHERE (内容) -->
<!-- 2. suffix:在 trim 标签内容后添加的后缀 -->
<trim suffix="ORDER BY id">
<!-- 内容 -->
</trim>
<!-- 生成:(内容) ORDER BY id -->
<!-- 3. prefixOverrides:要去除的前缀(支持正则表达式,用 | 分隔) -->
<trim prefix="WHERE" prefixOverrides="AND|OR">
<if test="condition1">AND col1 = val1</if>
<if test="condition2">AND col2 = val2</if>
</trim>
<!-- 生成:WHERE col1 = val1 AND col2 = val2 -->
<!-- 4. suffixOverrides:要去除的后缀(支持正则表达式,用 | 分隔) -->
<trim prefix="SET" suffixOverrides=",">
<if test="col1 != null">col1 = val1,</if>
<if test="col2 != null">col2 = val2,</if>
</trim>
<!-- 生成:SET col1 = val1, col2 = val2 -->
<!-- 错误写法:忘记配置 prefixOverrides -->
<select id="selectBad" resultMap="BaseResultMap">
SELECT * FROM user
<trim prefix="WHERE">
<if test="username != null">
AND username = #{username} <!-- 第一个条件前有 AND -->
</if>
</trim>
</select>
<!-- 生成错误SQL:SELECT * FROM user WHERE AND username = ? -->
<!-- 正确写法:配置 prefixOverrides="AND|OR" -->
<select id="selectGood" resultMap="BaseResultMap">
SELECT * FROM user
<trim prefix="WHERE" prefixOverrides="AND|OR">
<if test="username != null">
AND username = #{username}
</if>
</trim>
</select>
<!-- 生成正确SQL:SELECT * FROM user WHERE username = ? -->
<!-- 错误写法:忘记配置 suffixOverrides -->
<update id="updateBad">
UPDATE user
<trim prefix="SET">
<if test="username != null">
username = #{username}, <!-- 最后一个字段后有逗号 -->
</if>
</trim>
WHERE id = #{id}
</update>
<!-- 生成错误SQL:UPDATE user SET username = ?, -->
<!-- 正确写法:配置 suffixOverrides="," -->
<update id="updateGood">
UPDATE user
<trim prefix="SET" suffixOverrides=",">
<if test="username != null">
username = #{username},
</if>
</trim>
WHERE id = #{id}
</update>
<!-- 生成正确SQL:UPDATE user SET username = ? WHERE id = ? -->
<!-- 复杂场景:trim 可以嵌套使用 -->
<select id="selectComplex" resultMap="BaseResultMap">
SELECT * FROM user
<trim prefix="WHERE" prefixOverrides="AND|OR">
<!-- 外层 trim 处理 WHERE -->
<if test="query != null">
<!-- 内层 trim 处理分组条件 -->
<trim prefix="(" prefixOverrides="AND|OR" suffix=")">
<if test="query.username != null">
AND username LIKE #{query.username}
</if>
<if test="query.email != null">
AND email LIKE #{query.email}
</if>
</trim>
</if>
<if test="status != null">
AND status = #{status}
</if>
</trim>
</select>
<!-- 生成SQL:SELECT * FROM user WHERE (username LIKE ? AND email LIKE ?) AND status = ? -->
<!-- trim 标签:最灵活,可自定义前后缀和去除规则 -->
<trim prefix="WHERE" prefixOverrides="AND|OR" suffix="LIMIT 10">
<!-- 复杂场景 -->
</trim>
<!-- where 标签:trim的简化版,固定处理WHERE和AND/OR -->
<where>
<if test="condition1">AND col1 = val1</if>
<if test="condition2">AND col2 = val2</if>
</where>
<!-- 等价于:<trim prefix="WHERE" prefixOverrides="AND|OR"> -->
<!-- set 标签:trim的简化版,固定处理SET和逗号 -->
<set>
<if test="col1 != null">col1 = val1,</if>
<if test="col2 != null">col2 = val2,</if>
</set>
<!-- 等价于:<trim prefix="SET" suffixOverrides=","> -->
<!-- 最佳实践:简单场景用 where/set,复杂场景用 trim -->
<trim>标签核心是"智能拼接",自动处理 SQL 前后缀和多余关键字,避免语法错误prefix(前缀)、suffix(后缀)、prefixOverrides(去前缀)、suffixOverrides(去后缀)<where>/<set>简化版,复杂场景用 <trim>完整版