MyBatis-Plus输出完整SQL(带参数)的三种方案

2025-02-07日常编程271968

当我们使用 mybatis-plus 时,可能会遇到SQL 不能直接执行,调试也不方便的情况,那么,如何打印完整 SQL(带参数)呢?本篇文章将介绍 3 种实现方式,并对比它们的优缺点,需要的朋友可以参考下

目录
  • 为什么 MyBatis Plus 默认 SQL 日志没有参数?
  • 方案 1:使用 SqlLogInterceptor(推荐)
  • 方案 2:自定义 MyBatis Interceptor
    • 编写 Interceptor:
  • 方案 3:开启 MyBatis 日志(手动拼接 SQL)
    • 最佳方案对比与选择
      • 结论:哪种方式适合你?

        为什么 MyBatis Plus 默认 SQL 日志没有参数?

        当你使用 mybatis-plus 时,可能会遇到这样的情况:

        Preparing: SELECT id, name, `desc` FROM author WHERE name = ?
        Parameters: 刘禹锡(String)
        

        这导致 SQL 不能直接执行,调试也不方便。那么,如何打印完整 SQL(带参数)呢?本篇文章将介绍 3 种实现方式,并对比它们的优缺点。

        方案 1:使用 SqlLogInterceptor(推荐)

        从 MyBatis Plus 3.5.3 版本 开始,官方提供了 SqlLogInterceptor,可以自动替换 SQL 语句中的 ? 为实际参数。

        配置方式:

        import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
        import com.baomidou.mybatisplus.extension.plugins.inner.SqlLogInterceptor;
        import org.springframework.context.annotation.Bean;
        import org.springframework.context.annotation.Configuration;
        
        @Configuration
        public class MyBatisPlusConfig {
        
            @Bean
            public MybatisPlusInterceptor mybatisPlusInterceptor() {
                MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
                interceptor.addInnerInterceptor(new SqlLogInterceptor()); // ✅ 让 SQL 带参数
                return interceptor;
            }
        }
        

        效果:

        Executing SQL: SELECT id, name, `desc` FROM author WHERE name = '刘禹锡'
        

        优点:

        • 官方支持,无侵入,简单易用
        • 低性能开销,仅影响日志输出
        • 适用于 MyBatis Plus

        缺点:

        • 只适用于 MyBatis Plus(普通 MyBatis 需要用方案 2)

        方案 2:自定义 MyBatis Interceptor

        如果你使用的是 原生 MyBatis,或者想要更灵活的日志格式,可以 自定义 Interceptor

        编写 Interceptor:

        @Intercepts({
            @Signature(type = Executor.class, method = "query", args = {
                MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
            @Signature(type = Executor.class, method = "update", args = {
                MappedStatement.class, Object.class})
        })
        @Slf4j
        public class SqlInterceptor implements Interceptor {
            @Override
            public Object intercept(Invocation invocation) throws Throwable {
                long startTime = System.currentTimeMillis();
                Object proceed = invocation.proceed();
                long endTime = System.currentTimeMillis();
        
                String sql = generateSql(invocation);
                log.info("\n 执行SQL耗时:{}ms \n 执行SQL:{}", endTime - startTime, sql);
                return proceed;
            }
        
            private static String generateSql(Invocation invocation) {
                MappedStatement statement = (MappedStatement) invocation.getArgs()[0];
                Object parameter = invocation.getArgs().length > 1 ? invocation.getArgs()[1] : null;
                BoundSql boundSql = statement.getBoundSql(parameter);
        
                String sql = boundSql.getSql().replaceAll("[\\s]+", " ");
                for (ParameterMapping param : boundSql.getParameterMappings()) {
                    Object value = boundSql.getAdditionalParameter(param.getProperty());
                    sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(getParameterValue(value)));
                }
                return sql;
            }
        
            private static String getParameterValue(Object object) {
                return object instanceof String ? "'" + object + "'" : String.valueOf(object);
            }
        
            @Override
            public Object plugin(Object target) {
                return Plugin.wrap(target, this);
            }
        }
        

        优点:

        • 适用于 原生 MyBatis 和 MyBatis Plus
        • 可自定义日志格式,控制输出内容

        缺点:

        • 需要手动编写,稍微复杂一点
        • 性能开销略大(需要解析 SQL 并替换参数)

        方案 3:开启 MyBatis 日志(手动拼接 SQL)

        如果只是 临时调试,可以在 application.yml 配置 MyBatis 日志:

        mybatis-plus:
          configuration:
            log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
        

        然后,手动拼接 SQL 进行调试。

        优点:

        • 无代码改动,适合临时调试

        缺点:

        • 仍然是 Preparing: xxx 和 Parameters: xxx 的分离格式
        • 不能直接复制执行

        最佳方案对比与选择

        方案 适用场景 侵入性 性能开销 适用框架
        SqlLogInterceptor MyBatis Plus MyBatis Plus
        自定义 Interceptor 需要特殊格式 中等 MyBatis & MyBatis Plus
        MyBatis 日志 临时调试 MyBatis & MyBatis Plus

        结论:哪种方式适合你?

        • 推荐:使用 SqlLogInterceptor,简单、无侵入,适用于 MyBatis Plus
        • 进阶:自定义 Interceptor,适用于 MyBatis,可自定义日志格式。
        • 临时调试:开启 MyBatis 日志,但不自动替换 ?

        到此这篇关于MyBatis-Plus输出完整SQL(带参数)的三种方案的文章就介绍到这了,更多相关MyBatis-Plus输出完整SQL内容请搜索北冥有鱼以前的文章或继续浏览下面的相关文章希望大家以后多多支持北冥有鱼!

        您可能感兴趣的文章:

        • SpringBoot 整合Mybatis-Plus并输出SQL日志示例详解
        • MyBatis-Plus使用sl4j日志打印SQL的代码详解
        • MyBatis-Plus自定义SQL和复杂查询的实现
        • MyBatis/mybatis-plus项目打印SQL的方法实现
        • mybatis-plus实现打印完整sql语句
        本文地址:https://www.ufcn.cn/tutorials/3368280.html

        如非特殊说明,本站内容均来自于网友自主分享,概不代表本站观点,如有任何问题我们都将在收到反馈后的第一时间进行处理!