SpringBoot3+MyBatis-Plus SQL可视化调试实战
1. 项目概述
作为一名长期奋战在业务开发一线的Java工程师,我深知排查SQL问题的痛苦。每次看到MyBatis日志里那一串串问号占位符,都忍不住想摔键盘。手动拼接SQL参数不仅耗时耗力,还容易出错;想统计SQL执行耗时更是要各种加日志、查监控,效率极其低下。
最近在SpringBoot3项目中实践了一套SQL可视化调试方案,完美解决了这些问题。这套方案的核心优势在于:
- 零侵入:无需修改任何业务代码
- 即插即用:添加依赖后立即生效
- 完整SQL展示:直接输出带真实参数的SQL语句
- 执行耗时统计:自动计算每条SQL的执行时间
2. 环境准备
2.1 基础环境要求
在开始配置前,请确保你的开发环境满足以下要求:
- SpringBoot版本:3.2.5(最低要求3.0+)
- ORM框架:MyBatis-Plus 3.5.3+
- 数据库:MySQL 8.0(其他数据库也支持,配置略有不同)
- JDK版本:17+
提示:虽然方案主要针对SpringBoot3设计,但经过测试在SpringBoot2.7+版本也能正常工作,只是部分配置项可能需要调整。
2.2 开发工具建议
为了获得最佳调试体验,推荐使用以下工具组合:
- IDE:IntelliJ IDEA(社区版即可)
- 数据库客户端:DBeaver或Navicat
- 项目构建工具:Maven 3.8+
- 终端工具:支持ANSI颜色的终端(如Windows Terminal)
3. 核心依赖配置
3.1 Maven依赖引入
方案的核心是p6spy组件,它通过代理模式拦截JDBC操作。推荐使用starter简化配置:
<!-- SQL可视化调试核心starter --> <dependency> <groupId>com.github.gavlyukovskiy</groupId> <artifactId>p6spy-spring-boot-starter</artifactId> <version>2.0.0</version> </dependency> <!-- 以下是项目原有依赖,检查是否已存在 --> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.3.1</version> </dependency>3.2 依赖选择建议
在实际项目中,可能会遇到以下两种场景:
- 全新项目:直接使用上述starter方案最省心
- 已有项目改造:
- 如果原项目使用了复杂的数据源配置(如多数据源),可能需要手动配置
- 对于Spring Cloud项目,注意检查是否与其他数据源组件冲突
踩坑记录:曾经在一个多数据源项目中直接引入starter导致启动失败,后来发现需要排除自动配置类。解决方案是在@SpringBootApplication中添加exclude = {P6SpyAutoConfiguration.class},然后手动配置。
4. 详细配置指南
4.1 基础配置(application.yml)
spring: datasource: url: jdbc:mysql://localhost:3306/your_db?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false username: root password: your_password driver-class-name: com.mysql.cj.jdbc.Driver type: com.zaxxer.hikari.HikariDataSource # 关闭MyBatis-Plus原生日志避免重复 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.nologging.NoLoggingImpl # SQL调试配置 decorator: datasource: p6spy: logging: sysout log-format: "SQL执行耗时: %(executionTime)ms | 执行时间: %(currentTime) | 完整SQL: %(sql)"4.2 高级配置(spy.properties)
在resources目录下创建spy.properties文件:
# 日志格式化(适配MyBatis-Plus) logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger # 日志输出到控制台 appender=com.p6spy.engine.spy.appender.StdoutLogger # 启用前缀标识 useprefix=true # 排除无用日志类别 excludecategories=info,debug,result,commit,resultset # 时间格式化 dateformat=yyyy-MM-dd HH:mm:ss # 真实数据库驱动 driverlist=com.mysql.cj.jdbc.Driver # 慢SQL检测(单位:秒) outagedetection=true outagedetectioninterval=24.3 配置项详解
logMessageFormat:
- 默认格式较简单,使用MyBatis-Plus专用格式器输出更清晰
- 支持自定义实现,可继承com.p6spy.engine.spy.appender.FormattedLogger
excludecategories:
- 过滤掉不关心的日志类型,使输出更简洁
- 常见值:info,debug,result,commit,resultset,batch
outagedetection:
- 慢SQL检测功能,超过阈值的SQL会特别标注
- 生产环境建议关闭,避免性能开销
5. 实战效果演示
5.1 控制台输出示例
SQL执行耗时: 32ms | 执行时间: 2026-03-21 15:30:22 | 完整SQL: SELECT id,username,phone FROM t_user WHERE id = 1 AND status = 0; SQL执行耗时: 45ms | 执行时间: 2026-03-21 15:30:30 | 完整SQL: INSERT INTO t_user(username,phone,create_time) VALUES ('张三','13800138000','2026-03-21 15:30:30');5.2 功能亮点
参数可视化:
- 所有?占位符都被替换为实际值
- 字符串类型自动添加引号
- NULL值明确显示
执行耗时:
- 精确到毫秒级
- 包含网络往返时间
- 可用于性能分析
直接复制执行:
- 输出的SQL可直接粘贴到客户端工具执行
- 特别适合复杂查询调试
6. 生产环境管理
6.1 安全注意事项
绝对禁止在生产环境开启此功能,原因包括:
- 日志会暴露真实数据
- 增加性能开销
- 可能泄露敏感信息
6.2 环境隔离方案
方案一:Maven Profile
<profiles> <profile> <id>dev</id> <activation> <activeByDefault>true</activeByDefault> </activation> <dependencies> <dependency> <groupId>com.github.gavlyukovskiy</groupId> <artifactId>p6spy-spring-boot-starter</artifactId> <version>2.0.0</version> </dependency> </dependencies> </profile> </profiles>方案二:配置开关
spring: profiles: active: dev --- spring: config: activate: on-profile: prod decorator: datasource: p6spy: enable: false7. 常见问题排查
7.1 驱动加载失败
现象:启动时报"Driver not found"
解决方案:
- 检查driver-class-name是否正确
- 如果手动配置,确保url以jdbc:p6spy:开头
- 推荐使用starter自动配置
7.2 日志重复输出
现象:同一条SQL被打印多次
解决方案:
- 确认关闭了MyBatis原生日志
- 检查是否有多个数据源被代理
- 在spy.properties中设置excludecategories
7.3 性能下降明显
现象:启用后请求响应变慢
解决方案:
- 检查是否在生产环境误开启
- 降低日志级别
- 考虑使用文件输出代替控制台
8. 进阶使用技巧
8.1 日志文件输出
# 输出到文件 appender=com.p6spy.engine.spy.appender.FileLogger # 日志文件路径 logfile=spy.log # 每日滚动 appender.properties=log.dateformat=yyyy-MM-dd8.2 自定义日志格式
logMessageFormat=com.yourpackage.CustomLogger需要实现自定义类:
public class CustomLogger extends FormattedLogger { @Override public String formatMessage(int connectionId, String now, long elapsed, String category, String prepared, String sql) { // 自定义格式逻辑 } }8.3 敏感数据脱敏
通过自定义过滤器实现:
public class SensitiveFilter implements P6LogQueryFilter { @Override public boolean logQuery(String query) { // 实现脱敏逻辑 return true; } }在spy.properties中注册:
filter=com.yourpackage.SensitiveFilter这套方案在我负责的多个项目中已经稳定运行超过半年,极大提升了开发调试效率。特别是在处理复杂业务逻辑时,能够快速定位SQL问题,平均每个需求节省约2小时的调试时间。
