MyBatis-Plus XML 与 注解混合使用指南
适用版本: MyBatis-Plus 3.0+(主流版本兼容)
适用场景: 简单 CRUD 用注解,复杂 SQL 用 XML,兼顾开发效率与灵活性。
一、核心概念
1.1 MyBatis-Plus 简介
MyBatis-Plus(简称 MP)是 MyBatis 的增强工具,简化 CRUD 操作,提供 BaseMapper<T>
接口,无需编写 XML 即可完成基础操作。
1.2 注解 vs XML
特性 | 注解(Annotation) | XML 映射文件 |
---|---|---|
开发速度 | ⚡ 快(一行搞定) | ⏳ 慢(需写文件) |
可读性 | 简单 SQL 清晰 | 复杂 SQL 更易读 |
动态 SQL | 有限支持 | 完全支持(<if> , <choose> 等) |
维护性 | 小项目好 | 大项目更易维护 |
混合使用 | ✅ 支持 | ✅ 支持 |
1.3 混合使用原则
- 简单 CRUD:使用
@Select
,@Insert
,@Update
,@Delete
注解 - 复杂查询(多表、动态条件、分页、子查询等):使用 XML 文件
- XML 优先级高于注解:同名方法在 XML 中定义后,注解失效。
二、详细操作步骤(手把手教学)
步骤 1:添加依赖(Maven)
<dependencies>
<!-- Spring Boot Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- MyBatis-Plus -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
<!-- 数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Lombok(可选) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
步骤 2:配置 application.yml
server:
port: 8080
spring:
datasource:
url: jdbc:mysql://localhost:3306/test_db?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-plus:
# XML 映射文件路径
mapper-locations: classpath:mapper/*.xml
# 实体类包路径(自动识别 @TableName)
type-aliases-package: com.example.demo.entity
configuration:
# 开启驼峰命名转换
map-underscore-to-camel-case: true
# 打印 SQL(开发环境)
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
步骤 3:创建实体类(Entity)
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
@Data
@TableName("user") // 指定表名
public class User {
@TableId(type = IdType.AUTO)
private Long id;
@TableField("name")
private String name;
@TableField("email")
private String email;
@TableField(exist = false) // 非数据库字段
private String remark;
}
步骤 4:创建 Mapper 接口
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface UserMapper extends BaseMapper<User> {
// 注解方式:简单查询
@Select("SELECT * FROM user WHERE name = #{name}")
User selectByName(@Param("name") String name);
// 注解方式:更新
@Update("UPDATE user SET email = #{email} WHERE name = #{name}")
int updateEmailByName(@Param("name") String name, @Param("email") String email);
// XML 方式:复杂查询(分页 + 多条件)
IPage<User> selectUserPage(Page<User> page, @Param("query") UserQuery query);
}
步骤 5:创建 XML 映射文件
在 resources/mapper/UserMapper.xml
:
<?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="com.example.demo.mapper.UserMapper">
<!-- 复杂分页查询 -->
<select id="selectUserPage" resultType="com.example.demo.entity.User">
SELECT id, name, email
FROM user
<where>
<if test="query != null">
<if test="query.name != null and query.name != ''">
AND name LIKE CONCAT('%', #{query.name}, '%')
</if>
<if test="query.email != null and query.email != ''">
AND email = #{query.email}
</if>
</if>
</where>
ORDER BY id DESC
</select>
</mapper>
💡 注意:
namespace
必须是 Mapper 接口的全限定名。
步骤 6:创建查询条件类(可选)
import lombok.Data;
@Data
public class UserQuery {
private String name;
private String email;
}
步骤 7:Service 层调用示例
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
// 使用注解查询
public User getUserByName(String name) {
return userMapper.selectByName(name);
}
// 使用 XML 分页查询
public IPage<User> getUserPage(int pageNum, int pageSize, UserQuery query) {
Page<User> page = new Page<>(pageNum, pageSize);
return userMapper.selectUserPage(page, query);
}
}
步骤 8:Controller 测试
@RestController
@RequestMapping("/users")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/byname/{name}")
public User getUser(@PathVariable String name) {
return userService.getUserByName(name);
}
@GetMapping("/page")
public IPage<User> getPage(
@RequestParam(defaultValue = "1") int pageNum,
@RequestParam(defaultValue = "10") int pageSize,
UserQuery query) {
return userService.getUserPage(pageNum, pageSize, query);
}
}
三、常见错误与解决方案
错误现象 | 原因 | 解决方案 |
---|---|---|
Invalid bound statement (not found) |
XML 文件未被扫描 | 检查 mapper-locations 路径是否正确 |
Property 'sqlSessionFactory' or 'sqlSessionTemplate' is required |
未启用 MP 自动配置 | 确保主类加 @SpringBootApplication |
注解 SQL 不生效 | XML 中定义了同名方法 | 删除 XML 方法或注解方法 |
参数未映射(null) | 未使用 @Param |
多参数必须加 @Param |
表名或字段名映射错误 | 未开启驼峰转换 | map-underscore-to-camel-case: true |
四、注意事项
- 命名空间必须一致:XML 中
namespace
= Mapper 接口全路径。 - 方法名必须一致:XML 中
<select id="xxx">
必须与接口方法名相同。 - 参数绑定:使用
@Param("xxx")
显式命名参数,尤其多参数或复杂对象。 - 返回类型一致:XML
resultType
必须与接口返回类型匹配。 - XML 优先级更高:一旦 XML 定义了方法,注解将被忽略。
五、使用技巧
5.1 使用 @Results
注解处理复杂映射
@Results({
@Result(property = "id", column = "id", id = true),
@Result(property = "name", column = "user_name")
})
@Select("SELECT id, user_name FROM user WHERE id = #{id}")
User selectByIdCustom(Long id);
5.2 利用 MP 内置方法减少 XML
// 直接使用 BaseMapper 方法,无需写 XML
List<User> users = userMapper.selectList(
new QueryWrapper<User>().like("name", "张").eq("status", 1)
);
5.3 动态 SQL 用 XML,静态用注解
保持代码清晰,避免在注解中拼接大量 SQL 字符串。
六、最佳实践
实践 | 说明 |
---|---|
✅ 简单 CRUD 用注解 | 提高开发效率 |
✅ 复杂查询用 XML | 易维护、支持动态 SQL |
✅ 统一 XML 路径 | 如 mapper/*.xml |
✅ 使用 @Param |
避免参数绑定错误 |
✅ 开启驼峰转换 | 避免字段映射问题 |
✅ 分页使用 MP 分页插件 | 避免手写分页 SQL |
七、性能优化建议
- 避免 N+1 查询:使用 JOIN 一次性查出关联数据,而非循环查数据库。
- 合理使用缓存:开启 MyBatis 二级缓存(
@CacheNamespace
)。 - SQL 优化:为查询字段加索引,避免
SELECT *
。 - 分页优化:大数据量使用
keySet 分页
或游标分页
,避免LIMIT offset, size
性能下降。 - 批量操作:使用
saveBatch()
、updateBatchById()
批量处理。
八、总结
使用方式 | 适用场景 | 推荐指数 |
---|---|---|
注解 | 简单查询、更新、插入 | ⭐⭐⭐⭐☆ |
XML | 复杂查询、动态 SQL、多表联查 | ⭐⭐⭐⭐⭐ |
混合使用 | 大多数企业项目 | ✅ 强烈推荐 |
✅ 结论:注解 + XML 混合使用是 MyBatis-Plus 的黄金组合,兼顾开发效率与灵活性。