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

 更新时间:2025年02月06日 10:02:03   作者:( •̀∀•́ )920  
当我们使用 mybatis-plus 时,可能会遇到SQL 不能直接执行,调试也不方便的情况,那么,如何打印完整 SQL(带参数)呢?本篇文章将介绍 3 种实现方式,并对比它们的优缺点,需要的朋友可以参考下

为什么 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 的分离格式
  • 不能直接复制执行

最佳方案对比与选择

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

结论:哪种方式适合你?

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

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

相关文章

  • springboot入门篇HelloWorld(图文教程)

    springboot入门篇HelloWorld(图文教程)

    springboot springboot是一个全新的框架,它设计的目的简化spring项目的初始环境的搭建和开发,下面这篇文章主要给大家介绍了关于springboot入门篇HelloWorld的相关资料,需要的朋友可以参考下
    2023-12-12
  • Spring容器刷新prepareRefresh第一步

    Spring容器刷新prepareRefresh第一步

    这篇文章主要为大家介绍了Spring容器刷新prepareRefresh第一步示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • Java Kafka实现延迟队列的示例代码

    Java Kafka实现延迟队列的示例代码

    kafka作为一个使用广泛的消息队列,很多人都不会陌生。本文将利用Kafka实现延迟队列,文中的示例代码讲解详细,感兴趣的小伙伴可以尝试一下
    2022-08-08
  • Java 线程池全面总结与详解

    Java 线程池全面总结与详解

    在一个应用程序中,我们需要多次使用线程,也就意味着,我们需要多次创建并销毁线程。而创建并销毁线程的过程势必会消耗内存。而在Java中,内存资源是及其宝贵的,所以,我们就提出了线程池的概念
    2021-10-10
  • Spring Cloud Alibaba微服务组件Sentinel实现熔断限流

    Spring Cloud Alibaba微服务组件Sentinel实现熔断限流

    这篇文章主要为大家介绍了Spring Cloud Alibaba微服务组件Sentinel实现熔断限流过程示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-06-06
  • java读取XML文件的四种方法总结(必看篇)

    java读取XML文件的四种方法总结(必看篇)

    下面小编就为大家带来一篇java读取XML文件的四种方法总结(必看篇)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • MyBatis 与 Spring Data JPA 核心对比总结(选型指南与最佳实践)

    MyBatis 与 Spring Data JPA 核心对比总结(选型指南与最佳实践)

    MyBatis和Spring Data JPA是Java两大主流持久层框架,分别代表SQL可控性与面向对象开发效率的两种设计哲学,本文给大家介绍MyBatis与Spring Data JPA核心对比总结,感兴趣的朋友跟随小编一起看看吧
    2025-11-11
  • Mybatis Mapper中多参数方法不使用@param注解报错的解决

    Mybatis Mapper中多参数方法不使用@param注解报错的解决

    这篇文章主要介绍了Mybatis Mapper中多参数方法不使用@param注解报错的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教。
    2022-01-01
  • JAVA自定义异常使用方法实例详解

    JAVA自定义异常使用方法实例详解

    这篇文章主要介绍了JAVA自定义异常使用方法实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • Java JDK与cglib动态代理有什么区别

    Java JDK与cglib动态代理有什么区别

    这篇文章主要介绍了Java JDK动态代理和cglib动态代理的区别文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2023-03-03

最新评论