1. 流程
- 配置 mapper XML 扫描路径
- 在 Mapper 接口中定义方法
- 编写对应的 XML SQL
- 测试调用
2. 逐行代码详解
2.1 配置 mapper 路径(application.yml)
mybatis-plus:
mapper-locations: "classpath*:/mapper/**.xml" # Mapper.xml
- 作用:告诉 Spring Boot,去哪里找 MyBatis 的 XML 映射文件
- 路径规则:
classpath*:/mapper/**.xml表示resources/mapper/目录下所有.xml文件都会被扫描到
2.2 Mapper 接口定义
@Mapper
public interface UserInfoMapper extends BaseMapper<UserInfo> {
List<UserInfo> queryUserByCustom2(@Param(Constants.WRAPPER)Wrapper<UserInfo> wrapper);
}
@Mapper:让 MyBatis 识别这个接口@Param(Constants.WRAPPER):
-
- 关键注解,值就是
ew - 告诉 MyBatis,这个参数在 XML 里要用
${ew.customSqlSegment}来引用
- 关键注解,值就是
- 方法名
queryUserByCustom2要和 XML 里的id完全一致
2.3 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.bite.mybatis.plus.mapper.UserInfoMapper">
<select id="queryUserByCustom2">
select id,username,password,age FROM user_info ${ew.customSqlSegment}
</select>
</mapper>
namespace:必须和 Mapper 接口的全类名一致<select id="queryUserByCustom2">:id必须和接口里的方法名完全一致${ew.customSqlSegment}:
-
- 核心功能,会自动把 Wrapper 里的条件,转换成完整的
WHERE ...片段 - 比如传了
.eq("username","admin"),就会生成WHERE username = 'admin'
- 核心功能,会自动把 Wrapper 里的条件,转换成完整的
2.4. 测试调用
@Test
void testQueryUserByCustom2(){
QueryWrapper<UserInfo> queryWrapper = new QueryWrapper<UserInfo>()
.eq("username","admin");
userInfoMapper.queryUserByCustom2(queryWrapper).forEach(System.out::println);
}
-
最终执行的 SQL:
select id,username,password,age FROM user_info WHERE username = 'admin'
3.关键原理
XML 方式和注解方式的核心逻辑完全一样:
- 你在 XML 里写
SELECT ... FROM ...实现自定义 SQL - 通过
${ew.customSqlSegment}接收 Wrapper 条件,自动拼接WHERE子句 - 区别只是 SQL 写在 XML 里,更适合复杂 SQL、多表联查等场景
4.易错点避坑
- namespace 写错 :必须和 Mapper 接口的全类名完全一致,否则会报
Invalid bound statement错误 - 方法名不匹配 :XML 里的
id必须和接口里的方法名完全一致 - 参数注解必须写 :
@Param(Constants.WRAPPER)不能少,否则 XML 里找不到ew对象 - 路径配置正确 :
mapper-locations要配置对,否则 XML 文件不会被加载
5. 和注解方式的对比
|--------|------------------|-------------------|-------------|
| 方式 | 优点 | 缺点 | 适用场景 |
| 注解方式 | 简单快捷,不用写 XML | 复杂 SQL 可读性差,不方便维护 | 简单查询、快速开发 |
| XML 方式 | 复杂 SQL 可读性强,方便维护 | 需要额外写 XML 文件 | 多表联查、复杂条件查询 |
6. 多表联查的 XML 写法
<select id="queryUserWithDept">
SELECT u.id, u.username, u.age, d.dept_name
FROM user_info u
LEFT JOIN dept d ON u.dept_id = d.id
${ew.customSqlSegment}
</select>
-
测试时传
Wrapper条件:QueryWrapper<UserInfo> wrapper = new QueryWrapper<>();
wrapper.gt("u.age", 18).eq("d.dept_name", "技术部"); -
自动生成 SQL:
SELECT u.id, u.username, u.age, d.dept_name
FROM user_info u
LEFT JOIN dept d ON u.dept_id = d.id
WHERE u.age > 18 AND d.dept_name = '技术部'