ReZero's Utopia.

sql打印的一种暴力解决方式

Word count: 448Reading time: 1 min
2021/01/23 Share

Sql log 失效

以 MyBatis 为例,因为其他辅助框架的不同,或者某些条件限制,导致日志按照官网配置后可能出现仍然无法打印的情况,这时候可能就会想到写sql拦截器自己拦截生成sql填充参数,但可能需要一定的开发时间。

本文直接挑明一种暴力打印的方式,不清楚是否广泛可用,但有兴趣的老哥们可以试一下。

Java 类加载优先级

会按照 classpath 的顺序去加载,遇到 全限定名相同的类 时只会加载第一个,而 classpath 目录的默认值是 ., 也就是当前目录。

换句话说当项目跑起来的时候会优先加载自己写的 class, 这是暴力方法的基础。

Sql的执行方法

MyBatis Mysql 为例,一直 debug 跟踪到 JDBC 层会找到这个方法 PrepareStatement.execute 方法(批量执行对应的(PrepareStatement.executeBatchInternal)),最开始的时候在这里找到了生成最终 payloadPacket 估计就是客户端发送包里有sql, 后来转念一想这个类中应该有个差不多生成 sql 的方法,的确就是 PrepareStatement.asSql ,到这其实结合刚刚的Java加载优先级机制暴力的方法已经出来了。

具体方案

jdbc 包中的 souce code 下载下来,(jetbrains idea 的话只需要点击下这个类的右上角有个 download source 的方法)下载成功后,按照该类包的路径在项目中创建一个同路径的包,然后将其放进去,同时修改 PrepareStatement.execute, 在其首部执行 (log.info(asSql())) 即可。(这里的 loglombok@SLF4J 生成的,可以根据自己的喜好选择打印的方式)

CATALOG
  1. 1. Sql log 失效
  2. 2. Java 类加载优先级
  3. 3. Sql的执行方法
  4. 4. 具体方案