MyBatis打印完整SQL需精准配置日志级别、自定义LogImpl将SQL升至INFO、通过Interceptor拼接真实参数,同时避免全局DEBUG和TRACE导致的性能与OOM问题。

MyBatis 打印完整 SQL 语句,关键在于让日志输出包含 SQL 文本、实际参数值和执行结果,同时避免过度日志干扰。单纯靠默认 DEBUG 级别只能看到带 ? 占位符的语句,真正“可直接执行”的完整 SQL 需要额外处理。日志级别调整不是简单设成 DEBUG 就完事,而是要精准控制范围、降低侵入性、适配环境需求。
用日志框架精准控制 SQL 输出范围
MyBatis 内部按包路径分级打日志:DEBUG 级别打印 SQL 和参数,TRACE 级别才追加结果集。因此,只需把 Mapper 接口所在包设为 DEBUG,其他包保持 INFO 或更高,就能只看 SQL 不刷屏。
- Spring Boot 中在 application.yml 里配置:
logging:<br> level:<br> com.example.mapper: debug
- Logback(logback-spring.xml)中:
<logger name="com.example.mapper" level="DEBUG" /> - Log4j2(log4j2.xml)中:
<Logger name="com.example.mapper" level="debug" />
让 SQL 日志升到 INFO 级别(适合生产排查)
默认 DEBUG 日志在生产环境开启会淹没关键信息。可通过自定义 Log 实现类,把 MyBatis 的 debug() 调用转为 info() 输出,既保留 SQL 可读性,又不拉低整体日志水位。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 写一个继承 org.apache.ibatis.logging.slf4j.Slf4jImpl 的类,重写
debug(String s)方法,内部调用logger.info(s) - 在 application.yml 中指定:
mybatis:<br> configuration:<br> log-impl: com.yourpackage.MyInfoSlf4jImpl
- 无需改日志框架配置,SQL 就自动出现在 INFO 日志流中,方便 grep 或 ELK 过滤
拦截器拼出带真实参数的完整 SQL
DEBUG 日志里的 Parameters: 18(Integer), true(Boolean) 还得手动替换,效率低。用 MyBatis Plus 的 InnerInterceptor 或原生 MyBatis 的 Interceptor,可在 Statement 准备阶段解析 BoundSql,把 #{} 替换成实际值,生成可复制粘贴的完整语句。
- 提取
BoundSql.getSql()和MappedStatement.getParameterMap() - 借助
MetaObject和TypeHandlerRegistry安全获取参数值,注意处理 null、集合、嵌套对象 - 用正则或 StringBuilder 拼接,例如将
WHERE status = ?→WHERE status = 1 - 建议加开关控制:开发环境开,生产环境关;或仅对慢 SQL 启用
避免踩坑的几个关键点
很多问题不是配置不对,而是细节没到位:
-
logImpl 必须显式指定:Spring Boot 自动装配可能 fallback 到 StdOutImpl(只走 System.out),导致 logback 配置失效。务必在 yml 中写明
log-impl: SLF4J或LOG4J2 - 不要全局设 org.mybatis 为 DEBUG:会打出大量内部日志(如 TypeHandler 加载、XML 解析),应限定到具体 mapper 包
-
结果集日志(TRACE)慎开:尤其查大表时,
<== Total: 50000后面跟着全部数据 toString(),极易 OOM - 动态 SQL 注意日志时机:日志是在 SQL 解析后、参数绑定前打的,所以看到的 SQL 是最终拼好的,但参数还没填入 —— 拦截器才是填参时机


















