💡 一、前言
在现代 Java Web 开发中,MyBatis 凭借其灵活性和高性能,成为众多开发者首选的 ORM 框架。而在 Spring Boot 项目中整合 MyBatis 后,合理使用其 XML 中的各种标签,不仅能简化数据库操作,还能提升代码可读性和维护性。
本文将深入讲解 MyBatis 提供的核心 XML 标签,结合实际业务场景,帮助你掌握从基础到高级的动态 SQL 编写技巧
(如果不太了解SpringBoot整合MyBatis的可以访问从零开始,手把手教你 Spring Boot 如何整合 MyBatis(超详细图文教程))。
🛠️ 二、环境准备
1. 添加依赖(pom.xml)
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MyBatis Starter -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<!-- MySQL 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
2. 配置数据源(application.yml)
spring:
datasource:
url: jdbc:mysql://localhost:3306/test_db
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.example.demo.model
📄 三、MyBatis 常用标签详解与实战
✅ 1. <if>
标签:条件判断
场景:根据用户输入的姓名和年龄进行模糊查询。
<select id="findUsers" resultType="User">
SELECT * FROM users
WHERE 1=1
<if test="name != null and name != ''">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="age != null">
AND age >= #{age}
</if>
</select>
✅ 2. <choose>/<when>/<otherwise>
:多条件选择
场景:优先按名称查询,没有名称则按年龄范围查询,都无则返回所有。
<select id="findUsersByChoose" resultType="User">
SELECT * FROM users
<where>
<choose>
<when test="name != null">
name LIKE CONCAT('%', #{name}, '%')
</when>
<when test="minAge != null and maxAge != null">
age BETWEEN #{minAge} AND #{maxAge}
</when>
<otherwise>
1=1
</otherwise>
</choose>
</where>
</select>
✅ 3. <where>
标签:智能拼接 WHERE 子句
该标签会自动处理 AND
或 OR
开头的问题,避免 SQL 语法错误。
<select id="searchUsers" resultType="User">
SELECT * FROM users
<where>
<if test="name != null">
name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="age != null">
AND age = #{age}
</if>
</where>
</select>
✅ 4. <set>
标签:更新操作时自动去除尾部逗号
场景:根据 ID 更新用户信息,仅更新非空字段。
<update id="updateUser">
UPDATE users
<set>
<if test="name != null">name = #{name},</if>
<if test="age != null">age = #{age}</if>
</set>
WHERE id = #{id}
</update>
✅ 5. <foreach>
标签:遍历集合或数组
场景:批量插入用户信息
<insert id="batchInsertUsers">
INSERT INTO users (name, age)
VALUES
<foreach collection="users" item="user" separator=",">
(#{user.name}, #{user.age})
</foreach>
</insert>
✅ 6. <trim>
标签:灵活控制前后缀
适用于更复杂的 SQL 拼接逻辑,比如手动控制 WHERE
、SET
、AND
等关键字。
<select id="dynamicQuery" resultType="User">
SELECT * FROM users
<trim prefix="WHERE" prefixOverrides="AND |OR ">
<if test="name != null">
name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="age != null">
AND age = #{age}
</if>
</trim>
</select>
✅ 7. <sql>
和 <include>
标签:复用 SQL 片段
场景:定义通用字段或子查询,减少重复代码。
<sql id="base_columns">id, name, age, email</sql>
<select id="getUserById" resultType="User">
SELECT <include refid="base_columns"/> FROM users WHERE id = #{id}
</select>
也可以带参数传递:
<sql id="condition_by_name">
<if test="name != null">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
</sql>
<select id="searchUsersWithCondition">
SELECT * FROM users
WHERE 1=1
<include refid="condition_by_name"/>
</select>
✅ 8. <bind>
标签:绑定变量表达式
场景:提前处理参数,提高 SQL 可读性。
<select id="searchByName" resultType="User">
<bind name="pattern" value="'%' + name + '%'" />
SELECT * FROM users WHERE name LIKE #{pattern}
</select>
🧪 四、测试接口与 Controller 示例
Mapper 接口:
@Mapper
public interface UserMapper {
public List<User> findUsers(@Param("name")String name,@Param("age") Integer age);
public int batchInsertUsers(@Param("users") List<User> users);
public int updateUser(User user);
}
Controller 示例:
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserMapper userMapper;
@GetMapping("/search")
public List<User> searchUsers(
@RequestParam(required = false) String name,
@RequestParam(required = false) Integer age) {
return userMapper.findUsers(name, age);
}
@PostMapping("/batch")
public void addUsers(@RequestBody List<User> users) {
userMapper.batchInsertUsers(users);
}
}
🔍 五、常见问题与调试技巧
问题描述 | 解决方案 |
---|---|
参数未生效或为空 | 使用 @Param 注解明确传参名 |
SQL 报错开头为AND 或 OR | 使用 <where> 自动处理 |
批量插入失败 | 检查数据库是否开启允许一次执行多个值插入 |
末尾有逗号报错 | MyBatis 会自动处理,无需手动删除 |
📘 六、最佳实践总结
标签 | 使用场景 | 建议 |
---|---|---|
<if> | 单个条件筛选 | 结合 <where> 使用效果更佳 |
<choose> | 多选一条件 | 更适合复杂条件分支 |
<where> | 构建 WHERE 子句 | 自动处理首尾多余的关键字 |
<set> | 构建 SET 子句 | 更新部分字段非常有用 |
<foreach> | 遍历集合 | 适用于 IN 查询、批量插入等 |
<trim> | 灵活控制 SQL 片段 | 当其他标签无法满足需求时使用 |
<sql> /<include> | 复用 SQL | 提升代码复用率 |
<bind> | 绑定变量 | 提高 SQL 可读性和灵活性 |
🧩 七、进阶技巧推荐
1. 分页 + 动态查询结合使用
<select id="searchUsersWithPage" resultType="User">
SELECT * FROM users
<where>
<if test="name != null">
name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="age != null">
AND age = #{age}
</if>
</where>
</select>
在 Service 层调用 PageHelper:
PageHelper.startPage(pageNum, pageSize);
List<User> users = userMapper.searchUsersWithPage(name, age);
return new PageInfo<>(users);
📝 八、结语
通过掌握 MyBatis 提供的各种 XML 标签,你可以轻松实现动态 SQL 构建,大大提升数据库操作的灵活性和可维护性。
希望这篇文章能帮助你更好地理解 MyBatis 中标签的使用方式。如果你觉得有用,欢迎点赞、收藏、转发给更多需要的朋友!