使用MyBatis/MyBatis Plus实现SQL日志打印与执行监控

一、MyBatis原生方式实现

1. 配置日志实现

MyBatis支持多种日志框架,可以通过以下方式配置:

图片[1]_使用MyBatis/MyBatis Plus实现SQL日志打印与执行监控_知途无界

方式1:在mybatis-config.xml中配置

<configuration>
    <settings>
        <setting name="logImpl" value="SLF4J"/> <!-- 可选值:SLF4J | LOG4J | LOG4J2 | JDK_LOGGING | COMMONS_LOGGING | STDOUT_LOGGING | NO_LOGGING -->
    </settings>
</configuration>

方式2:在Spring Boot配置文件中配置

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

2. 日志级别控制

在logback/log4j2配置文件中设置日志级别:

<!-- Logback示例 -->
<logger name="com.your.mapper" level="DEBUG"/>

3. 拦截器实现SQL监控

创建自定义拦截器监控SQL执行:

@Intercepts({
    @Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class}),
    @Signature(type = StatementHandler.class, method = "update", args = {Statement.class}),
    @Signature(type = StatementHandler.class, method = "batch", args = {Statement.class})
})
public class SqlMonitorInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        BoundSql boundSql = statementHandler.getBoundSql();

        long startTime = System.currentTimeMillis();
        try {
            return invocation.proceed();
        } finally {
            long endTime = System.currentTimeMillis();
            long costTime = endTime - startTime;

            String sql = boundSql.getSql();
            // 记录SQL执行信息
            log.info("SQL执行监控 - SQL: {}, 耗时: {}ms", sql, costTime);

            // 可以在这里实现慢SQL告警
            if (costTime > 1000) {
                log.warn("慢SQL警告 - 执行耗时: {}ms, SQL: {}", costTime, sql);
            }
        }
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
    }
}

注册拦截器:

@Bean
public SqlMonitorInterceptor sqlMonitorInterceptor() {
    return new SqlMonitorInterceptor();
}

二、MyBatis Plus实现方式

MyBatis Plus提供了更便捷的SQL日志和监控功能。

1. 基础配置

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 控制台打印SQL

2. 性能分析插件(3.2.0以下版本)

@Bean
public PerformanceInterceptor performanceInterceptor() {
    PerformanceInterceptor interceptor = new PerformanceInterceptor();
    interceptor.setMaxTime(1000); // 设置SQL执行最大时间,超过会抛出异常
    interceptor.setFormat(true);  // 格式化SQL语句
    return interceptor;
}

3. 新版执行分析插件(3.2.0+)

@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    // 添加性能分析插件
    interceptor.addInnerInterceptor(new PerformanceInnerInterceptor());
    return interceptor;
}

4. 完整SQL日志打印配置

@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();

    // SQL分析插件
    interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor()); // 防止全表更新与删除

    // 性能分析插件
    PerformanceInnerInterceptor performanceInterceptor = new PerformanceInnerInterceptor();
    performanceInterceptor.setMaxTime(1000); // 设置SQL执行最大时间,超过会抛出异常
    performanceInterceptor.setFormat(true);  // 格式化SQL语句
    interceptor.addInnerInterceptor(performanceInterceptor);

    return interceptor;
}

5. 自定义日志输出

@Bean
public MybatisPlusSqlInjector mybatisPlusSqlInjector() {
    return new MybatisPlusSqlInjector() {
        @Override
        public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass) {
            // 自定义SQL日志输出
            Configuration configuration = builderAssistant.getConfiguration();
            configuration.setLogPrefix(mapperClass.getName() + ".");
        }
    };
}

三、高级监控方案

1. 结合Micrometer实现指标监控

public class MetricsSqlMonitorInterceptor implements Interceptor {

    private final MeterRegistry meterRegistry;

    public MetricsSqlMonitorInterceptor(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
    }

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        String methodName = invocation.getMethod().getName();
        Timer.Sample sample = Timer.start(meterRegistry);

        try {
            return invocation.proceed();
        } finally {
            sample.stop(meterRegistry.timer("sql.execution.time", 
                "method", methodName));
        }
    }

    // 其他方法实现...
}

2. 结合Prometheus + Grafana可视化

@Bean
public SqlMonitorInterceptor sqlMonitorInterceptor(MeterRegistry meterRegistry) {
    return new MetricsSqlMonitorInterceptor(meterRegistry);
}

四、注意事项

  1. 生产环境:性能分析插件不建议在生产环境使用,会影响性能
  2. 日志级别:DEBUG级别会打印完整SQL和参数,注意敏感信息
  3. 慢SQL阈值:根据业务特点设置合理的慢SQL阈值
  4. 监控数据存储:考虑将监控数据持久化到数据库或监控系统

通过以上配置,你可以全面监控MyBatis/MyBatis Plus的SQL执行情况,及时发现性能问题并进行优化。

© 版权声明
THE END
喜欢就点个赞,支持一下吧!
点赞24 分享
评论 抢沙发
头像
欢迎您留下评论!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容