IDEA DEBUG调试时如何获取 MyBatis-Plus 动态拼接的 SQL?

目录

为什么日志不够用?

[核心思路:在 MyBatis 的"执行入口"设卡](#核心思路:在 MyBatis 的“执行入口”设卡)

[第一步:找到 `SqlSessionTemplate`](#第一步:找到 SqlSessionTemplate)

[第二步:在 `invoke` 方法上打个断点](#第二步:在 invoke 方法上打个断点)

[第三步:Debug 启动 + 触发查询](#第三步:Debug 启动 + 触发查询)

[第四步:找到 `BoundSql`,看 `sql` 字段](#第四步:找到 BoundSql,看 sql 字段)

进阶技巧:让调试更高效

[快速求值:Alt + F8](#快速求值:Alt + F8)

[条件断点:只抓你想看的 SQL](#条件断点:只抓你想看的 SQL)

临时打印条件片段(开发阶段用)

[想看到带参数的完整 SQL?可以,但要小心](#想看到带参数的完整 SQL?可以,但要小心)

其他方案

最后提醒几个坑

参考文档

结语


写过 MyBatis-Plus 的人都懂:`LambdaQueryWrapper` 用起来是真香,链式调用几行代码就能搞定一堆条件。但一旦结果不对,就容易懵------到底是条件写错了?还是 MP 根本没按你想的拼 SQL?

这时与其靠猜、靠日志、靠反复改代码试,不如直接在 IDEA 里打断点,看看它到底生成了什么 SQL。

为什么日志不够用?

很多人第一反应是开日志:

bash 复制代码
logging:
  level:
    com.yourpackage.mapper: debug

这样做确实能看到 SQL,但问题也明显:

  • 日志里全是 `?`,参数得自己脑补;
  • 一堆无关 SQL 刷屏,找目标语句像大海捞针;
  • 动态条件拼接逻辑藏在背后,看不出"为什么没拼上某个条件"。

而断点调试可以:

  • 精准定位到某一次查询;
  • 看到完整的、带结构的 SQL 字符串;
  • 顺带检查参数、条件对象、执行上下文。

核心思路:在 MyBatis 的"执行入口"打断点调式

MyBatis-Plus 底层还是 MyBatis,所有 SQL 最终都会经过 SqlSessionTemplate 的 invoke 方法。我们就在这里"蹲点"。

第一步:找到 `SqlSessionTemplate`

在 IDEA 里按 Ctrl + N(Mac 是 `Cmd + O`),输入 SqlSessionTemplate,选 org.mybatis.spring.SqlSessionTemplate。

> 别选错包!确保是 `mybatis-spring` 里的,不是你自己写的。

第二步:在 `invoke` 方法上打个断点

这个方法长这样:

java 复制代码
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    // ...
}

第三步:Debug 启动 + 触发查询

  • Debug 模式启动;
  • 调用你怀疑有问题的接口或方法;
  • 程序会在 `invoke` 处暂停。

第四步:找到 `BoundSql`,看 `sql` 字段

在 Debug 面板里,展开调用栈,找到类似这样的路径:

SqlSessionTemplate.invoke()

→ SqlSessionInterceptor.invoke()

→ DefaultSqlSession.selectList()

→ ...

→ BoundSql

点开 BoundSql 对象,里面的 `sql` 属性就是 MP 拼出来的完整 SQL。

比如你写了:

java 复制代码
wrapper.eq(User::getStatus, 1).like(User::getName, "张");

这里就能看到:

sql 复制代码
SELECT id, name, status FROM user WHERE status = ? AND name LIKE ?

虽然还是 `?`,但至少确认了条件拼对了没。

进阶技巧:让调试更高效

快速求值:Alt + F8

在断点暂停时,按 `Alt + F8`(Mac 是 `Option + F8`),直接输入:

java 复制代码
boundSql.getSql()

回车,立刻出结果,不用一层层点。

条件断点:只抓你想看的 SQL

右键断点 → **More** → 勾选 **Condition**,输入:

java 复制代码
method.getName().contains("selectList") && args[0].toString().contains("UserMapper")

这样只有查用户列表时才停,避免被其他 SQL 打断节奏。

临时打印条件片段(开发阶段用)

在代码里临时加一行:

java 复制代码
System.out.println("条件片段: " + wrapper.getSqlSegment());

输出类似:

条件片段: WHERE status = ? AND name LIKE ? ORDER BY create_time DESC

适合快速验证条件是否生效,不用进 Debug。

想看到带参数的完整 SQL?可以,但要小心

MyBatis 默认用预编译(PreparedStatement),所以 SQL 里是 `?`。参数存在 parameterObject 或 parameterMappings 中。

如果你真想拼成完整 SQL(比如 `WHERE name = '张三'`),可以用这个简化版工具类(仅用于本地调试!):

java 复制代码
public class DebugSqlHelper {
    public static String toCompleteSql(BoundSql boundSql, Configuration config) {
        String sql = boundSql.getSql().replaceAll("\\s+", " ");
        Object param = boundSql.getParameterObject();
        List<ParameterMapping> mappings = boundSql.getParameterMappings();

        if (mappings == null || mappings.isEmpty()) {
            return sql;
        }

        MetaObject metaParam = config.newMetaObject(param);
        for (ParameterMapping mapping : mappings) {
            String prop = mapping.getProperty();
            Object value = metaParam.getValue(prop);
            // 简单处理,实际需考虑类型、转义等
            sql = sql.replaceFirst("\\?", "'" + value + "'");
        }
        return sql;
    }
}

在 `Alt + F8` 里调用:

java 复制代码
DebugSqlHelper.toCompleteSql(boundSql, configuration)

注意:这仅用于开发调试!别提交到 Git,更别放生产。

其他方案

MyBatis Log Plugin可以自动格式化 SQL,但插件兼容性差,新版 IDEA 有时失效

p6spy:记录所有 SQL,配置麻烦,日志量大

开启 debug 日志:信息杂乱不容易找,并且看不到sql参数

最后提醒几个坑

  • **断点不触发?**检查是不是 Run 而不是 Debug;检查依赖是否冲突(比如引入了多个 MyBatis 版本)。
  • **SQL 看不到?**确认查询逻辑真的执行了(比如事务回滚、缓存命中可能跳过 SQL)。

参考文档

结语

调试不是"救火",而是开发的基本功。能快速看到 SQL,很多时候比读十遍文档都管用。

希望这个方法能帮你少走弯路。如果你有更骚的操作,也欢迎在评论区分享!

> 本文适用于 Spring Boot + MyBatis-Plus 3.5+ 项目,亲测有效。觉得有用?点个赞再走~

相关推荐
崎岖Qiu7 小时前
【设计模式笔记06】:单一职责原则
java·笔记·设计模式·单一职责原则
Hello.Reader8 小时前
Flink ExecutionConfig 实战并行度、序列化、对象重用与全局参数
java·大数据·flink
隐语SecretFlow8 小时前
隐语SecreFlow SCQL 1.0.0b1 发布:更完善的 SQL 支持与更高效的隐私查询引擎
数据库·sql
熊小猿8 小时前
在 Spring Boot 项目中使用分页插件的两种常见方式
java·spring boot·后端
paopaokaka_luck9 小时前
基于SpringBoot+Vue的助农扶贫平台(AI问答、WebSocket实时聊天、快递物流API、协同过滤算法、Echarts图形化分析、分享链接到微博)
java·vue.js·spring boot·后端·websocket·spring
ttghgfhhjxkl9 小时前
文档搜索引擎搜索模块的索引更新策略:实时增量与全量重建设计
数据库·搜索引擎
老华带你飞9 小时前
机器人信息|基于Springboot的机器人门户展示系统设计与实现(源码+数据库+文档)
java·数据库·spring boot·机器人·论文·毕设·机器人门户展示系统
StarRocks_labs9 小时前
StarRocks 在 Cisco Webex 的探索与实践
数据库·starrocks·json·存算分离·olap 技术栈
notion20259 小时前
Adobe Lightroom Classic下载与安装教程(附安装包) 2025最新版详细图文安装教程
java·数据库·其他·adobe