如何全局打印SQL日志

如何全局打印SQL日志

工作这么多年了,从没见过哪个项目里面有这个功能,不知道是缺乏想象力还是怎么滴。
MyBatisJPA(Hibernate) 都是开启他们自己的 SQL 打印。
假如中间有用 jdbc 直接查询的话,基本上就不走他们的打印了,毕竟也不属于 MyBatisJPA 的管辖范围。
那怎么样才能全局打印 SQL 日志呢?

如何下手

从需求来看,我们要全局拦截,首先就要想,谁能做到全局的查询都经它手呢?

那好像也就 jdbc 驱动能行了。

验证想法

jdbc 驱动这个,仔细想想它得分为两种,一种是规范,另一种就是具体实现。如果规范里面有相关定义可以让我们配置一下就能记录下所有的 SQL 记录,那便是极好的。
那如果规范里面没有,我们就只能把想法寄托于 MySQL JDBC Driver 了。

JDBC 规范

jdbc doc 基本上就能找到, 简单翻翻你就能得出结论: 没有

MySQL JDBC Driver

MySQL JDBC Doc 点开搜 logger 即能找到 Debugging/Profiling 章节。

说明这个 MySQL 的驱动集成了相关的功能,用于 debugprofiling,完美。

下面来看看支持的参数:

  • profileSQL
    Trace queries and their execution/fetch times to the configured ‘profilerEventHandler’
    Default: false
  • maxQuerySizeToLog
    Controls the maximum length of the part of a query that will get logged when profiling or tracing
    Default: 2048
  • profilerEventHandler
    Name of a class that implements the interface com.mysql.cj.log.ProfilerEventHandler that will be used to handle profiling/tracing events.
    Default: com.mysql.cj.log.LoggingProfilerEventHandler
  • logger
    默认是 com.mysql.cj.log.StandardLogger

说人话:
这个驱动支持上面这4个参数配置,其中都有默认值,整体默认表现就是: 没有表现
想要有得开一个参数:

profileSQL=true

这是最基本的需求了,这样配置以后就可以实现打印了。当然,打印的内容啥的都是默认的格式,想要改就得继续去修改这四个参数中的另外3个。

PS: jdbc 默认用的是自己实现的 log 不太好控制,最好还是自己重新实现一遍用 slf4j 处理一下。

样例


import com.mysql.cj.Query;
import com.mysql.cj.Session;
import com.mysql.cj.log.Log;
import com.mysql.cj.log.ProfilerEvent;
import com.mysql.cj.log.ProfilerEventHandler;
import com.mysql.cj.protocol.Resultset;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 此类应用于 jdbc url 中给 MySQL jdbc 定制日志打印用
 * https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-configuration-properties.html
 * @author Ray
 */
public class MyProfilerEventHandler implements ProfilerEventHandler {

    private static final Logger L = LoggerFactory.getLogger(SogProfilerEventHandler.class);

    @Override
    public void init(Log log) {

    }

    @Override
    public void destroy() {

    }

    @Override
    public void consumeEvent(ProfilerEvent evt) {

    }

    @Override
    public void processEvent(byte eventType, Session session, Query query, Resultset resultSet, long eventDuration, Throwable eventCreationPoint, String message) {
        // 3 == QUERY
        if (eventType == 3) {
            if (L.isDebugEnabled()) {
                L.debug("time:" + eventDuration + ";SQL:" + message);
            }

            if (eventDuration > 500) {
                L.warn("SLOW_QUERY!time:" + eventDuration + ";SQL:" + message);
            }
        }
    }
}

然后在 jdbc 配置里面添加参数

datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/xxx?characterEncoding=UTF-8&useUnicode=true&useSSL=false&serverTimeZone=Asia/Shanghai&profileSQL=true&profilerEventHandler=com.xxx.core.jpa.MyProfilerEventHandler

这样项目里面就有了日志了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值