1. MyBatisPlus打印SQL配置的必要性
在Java持久层开发中,SQL语句的调试和优化是每个开发者都会面临的挑战。MyBatisPlus作为MyBatis的增强工具,虽然提供了强大的CRUD操作能力,但在实际开发中,我们经常需要查看框架最终生成的SQL语句,以便进行性能调优或问题排查。
打印SQL日志的需求主要来自以下几个场景:
- 验证动态条件拼接是否正确
- 检查N+1查询问题
- 分析复杂联表查询的执行计划
- 监控批量操作的SQL生成
- 审计敏感数据操作
2. 基础配置方式
2.1 日志框架集成
MyBatisPlus支持通过多种日志框架输出SQL语句,以下是常见配置方式:
# application.yml 配置示例 mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 控制台输出或者使用SLF4J+Logback组合:
<!-- logback-spring.xml --> <logger name="com.baomidou.mybatisplus" level="DEBUG"/>2.2 多环境差异化配置
在实际项目中,我们通常需要区分开发环境和生产环境的日志级别:
@Configuration public class MyBatisPlusConfig { @Bean @Profile({"dev", "test"}) // 仅在开发测试环境生效 public PerformanceInterceptor performanceInterceptor() { PerformanceInterceptor interceptor = new PerformanceInterceptor(); interceptor.setFormat(true); // 格式化SQL输出 interceptor.setMaxTime(1000); // 设置SQL执行超时阈值(ms) return interceptor; } }3. 高级配置技巧
3.1 SQL美化输出
默认的SQL日志可能难以阅读,可以通过以下方式美化:
# 开启SQL格式化 mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.slf4j.Slf4jImpl logging.level.com.baomidou.mybatisplus=TRACE配合Logback的PatternLayout自定义输出格式:
<pattern>%d{yyyy-MM-dd HH:mm:ss} | %-5level | %logger{36} - %msg%n</pattern>3.2 敏感信息脱敏
对于包含敏感数据的SQL,建议配置脱敏规则:
public class SensitiveSqlLogger extends StdOutImpl { @Override public void debug(String text) { text = text.replaceAll("(password|mobile)=([^&]*)", "$1=****"); super.debug(text); } }4. 性能监控与优化
4.1 慢SQL监控
配置慢SQL阈值并输出警告:
public class SlowSqlInterceptor implements Interceptor { private static final long SLOW_SQL_THRESHOLD = 500; // ms @Override public Object intercept(Invocation invocation) { long start = System.currentTimeMillis(); Object result = invocation.proceed(); long duration = System.currentTimeMillis() - start; if(duration > SLOW_SQL_THRESHOLD) { Statement stmt = (Statement) invocation.getArgs()[0]; log.warn("Slow SQL detected: {} \n Execution time: {}ms", stmt.toString(), duration); } return result; } }4.2 执行计划分析
结合EXPLAIN命令自动分析关键SQL:
@Aspect @Component public class ExplainAspect { @Pointcut("execution(* com.baomidou.mybatisplus.core.mapper.BaseMapper.*(..))") public void mapperMethods() {} @Around("mapperMethods()") public Object addExplain(ProceedingJoinPoint pjp) throws Throwable { Object result = pjp.proceed(); if (needExplain()) { Object param = pjp.getArgs()[0]; if (param instanceof QueryWrapper) { QueryWrapper<?> wrapper = (QueryWrapper<?>) param; String explainSql = "EXPLAIN " + wrapper.getSqlSelect(); // 执行explain并记录结果 } } return result; } }5. 生产环境最佳实践
5.1 日志采样策略
在高并发环境下,全量SQL日志可能影响性能,建议采用采样策略:
public class SamplingSqlLogger extends Slf4jImpl { private static final AtomicLong COUNTER = new AtomicLong(); private static final int SAMPLE_RATE = 100; // 1%采样率 @Override public void debug(String s) { if (COUNTER.incrementAndGet() % SAMPLE_RATE == 0) { super.debug(s); } } }5.2 上下文增强
在分布式系统中,为SQL日志添加追踪信息:
public class TraceSqlInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) { MDC.put("traceId", TraceContext.getTraceId()); try { return invocation.proceed(); } finally { MDC.clear(); } } }6. 常见问题排查
6.1 日志不输出问题排查
- 检查日志级别是否正确设置
- 确认没有多个日志框架冲突
- 验证mybatis-plus配置是否正确加载
- 检查是否有自定义的Logger实现覆盖了默认行为
6.2 性能分析技巧
当发现SQL执行缓慢时:
- 先确认是网络延迟还是SQL本身问题
- 检查是否缺少索引
- 分析执行计划中的全表扫描
- 验证参数绑定是否正确
7. 扩展应用场景
7.1 审计日志记录
将关键SQL操作记录到审计表:
public class AuditLogInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) { Statement stmt = (Statement) invocation.getArgs()[0]; if (isAuditOperation(stmt)) { auditService.logOperation( getCurrentUser(), stmt.toString(), System.currentTimeMillis() ); } return invocation.proceed(); } }7.2 动态数据源路由
基于SQL特征实现读写分离:
public class DynamicDataSourceInterceptor { private static final Set<String> READ_OPERATIONS = Set.of("SELECT", "SHOW", "EXPLAIN"); public void beforeExecute(Statement stmt) { String sql = stmt.toString().toUpperCase(); boolean isRead = READ_OPERATIONS.stream().anyMatch(sql::startsWith); DynamicDataSourceHolder.setDataSourceType( isRead ? "read" : "write" ); } }在实际项目中,合理的SQL日志配置可以大幅提升开发调试效率。建议根据项目阶段灵活调整日志级别,开发环境可以使用DEBUG级别全面记录,而生产环境则应采用WARN级别配合采样策略。同时要注意日志中的敏感信息保护,避免数据泄露风险。