[Mybatis] XML 方式实现 MP 自定义 SQL + 条件构造器

1. 流程

  1. 配置 mapper XML 扫描路径
  2. 在 Mapper 接口中定义方法
  3. 编写对应的 XML SQL
  4. 测试调用

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'

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.易错点避坑

  1. namespace 写错 :必须和 Mapper 接口的全类名完全一致,否则会报 Invalid bound statement 错误
  2. 方法名不匹配 :XML 里的 id 必须和接口里的方法名完全一致
  3. 参数注解必须写 :@Param(Constants.WRAPPER) 不能少,否则 XML 里找不到 ew 对象
  4. 路径配置正确 :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 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 = '技术部'

相关推荐
Elastic 中国社区官方博客3 小时前
错误最多的服务运行正常:使用 ES|QL 从日志进行根因分析
大数据·运维·数据库·sql·elasticsearch·搜索引擎·全文检索
Seraphina364 小时前
DVWA(SQL Injection-High,XSS Reflected-Medium,XSS Stored-Medium)
数据库·经验分享·sql·网络安全·xss
2501_933670795 小时前
2027风控策略岗秋招准备:SQL、Excel、建模的优先级与项目路径
人工智能·sql·excel
其实防守也摸鱼6 小时前
网安自测题:掌握核心知识点的实用练习
linux·运维·服务器·前端·数据库·sql·xss
Shadow(⊙o⊙)6 小时前
MySQL C/C++链接MySQL使用
数据库·sql·mysql
Shadow(⊙o⊙)6 小时前
mysql为创建普通用户并创建库赋权
数据库·sql·mysql
Seraphina3616 小时前
SQLI-labs(一)黑盒全流程
sql·安全·web安全
做运维的阿瑞21 小时前
多表查询基础:INNER JOIN、LEFT JOIN、RIGHT JOIN
数据库·sql·mysql·算法
Seraphina361 天前
DVWA(SQL注入-low,medium,XSS反射-low)
前端·数据库·笔记·sql·网络安全·web·xss
代码什么用1 天前
使用javassist生成类 && MyBatis中接口代理机制及使用
mybatis