痛点概述
当我们在排查bug ,需要看执行的完整sql 时,在 console可以拿到如图的sql 
然后手工一个一个的替换问号占位符后,去MySQL 执行,看sql有木有什么问题。如果sql简单,那比较好说, 如果是个复杂sql,手动替换N个问号占位符,这种痛相信大家都经历过。 今天介绍的 MybatisFinalSqlPlugin 插件 正是解决了这样的痛点,可以直接抓到最终sql。
MybatisFinalSqlPlugin插件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| package com.anuo.app.common.datalayer.mybatisplugin; import com.google.common.base.Stopwatch; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.executor.statement.StatementHandler; import org.apache.ibatis.plugin.*; import org.apache.ibatis.reflection.MetaObject; import org.apache.ibatis.reflection.SystemMetaObject; import java.lang.reflect.Field; import java.sql.Connection; import java.sql.Statement; import java.util.Properties; @Intercepts({ @Signature(type = StatementHandler.class, method = "prepare", args = { Connection.class,Integer.class }) }) @Slf4j public class MybatisFinalSqlPlugin implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { Stopwatch stopwatch = Stopwatch.createStarted(); if (invocation.getTarget() instanceof StatementHandler) { Connection conn = (Connection) invocation.getArgs()[0]; StatementHandler handler = (StatementHandler) invocation.getTarget(); Statement stmt = handler.prepare(conn, 30); handler.parameterize(stmt); MetaObject metaObject = SystemMetaObject.forObject(stmt); while (metaObject.hasGetter("h")) { Object obj = metaObject.getValue("h"); metaObject = SystemMetaObject.forObject(obj); } Field hField = metaObject.getClass().getDeclaredField("originalObject"); hField.setAccessible(true); Object hObj = hField.get(metaObject); Field statementField = hObj.getClass().getDeclaredField("statement"); statementField.setAccessible(true); Object statementObj = statementField.get(hObj); Field stmtField = statementObj.getClass().getDeclaredField("stmt"); stmtField.setAccessible(true); Object stmtObj = stmtField.get(statementObj); Field statementArrivedField = stmtObj.getClass().getDeclaredField("statement"); statementArrivedField.setAccessible(true); Object statementArrivedFieldObj = statementArrivedField.get(stmtObj); String finalSql = statementArrivedFieldObj.toString(); finalSql = finalSql.substring(finalSql.lastIndexOf(":") + 1, finalSql.length() - 1); log.info("最终sql: \n " + finalSql); } log.debug("抓取最终sql 耗时:" + stopwatch); return invocation.proceed(); } @Override public Object plugin(Object target) { if (target instanceof StatementHandler) { return Plugin.wrap(target, this); } else { return target; } } @Override public void setProperties(Properties properties) { }
|