当前位置: 首页 > news >正文

基于Mybatis Plus的SQL输出拦截器。完美的输出打印 SQL 及执行时长、statement

我们需要想办法打印出完成的SQL,Mybatis为我们提供了 org.apache.ibatis.plugin.Interceptor接口,我们来实现该接口做一些打印SQL的工作

package org.springjmis.core.mp.plugins;import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.SystemClock;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.session.ResultHandler;
import org.springjmis.core.tool.utils.StringUtil;import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Statement;
import java.util.*;/*** 用于输出每条 SQL 语句及其执行时间** @author hubin nieqiurong TaoYu* @since 2016-07-07*/
@Slf4j
@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 SqlLogInterceptor implements Interceptor {private static final String DRUID_POOLED_PREPARED_STATEMENT = "com.alibaba.druid.pool.DruidPooledPreparedStatement";private static final String T4C_PREPARED_STATEMENT = "oracle.jdbc.driver.T4CPreparedStatement";private static final String ORACLE_PREPARED_STATEMENT_WRAPPER = "oracle.jdbc.driver.OraclePreparedStatementWrapper";private Method oracleGetOriginalSqlMethod;private Method druidGetSqlMethod;@Overridepublic Object intercept(Invocation invocation) throws Throwable {Statement statement;Object firstArg = invocation.getArgs()[0];if (Proxy.isProxyClass(firstArg.getClass())) {statement = (Statement) SystemMetaObject.forObject(firstArg).getValue("h.statement");} else {statement = (Statement) firstArg;}MetaObject stmtMetaObj = SystemMetaObject.forObject(statement);try {statement = (Statement) stmtMetaObj.getValue("stmt.statement");} catch (Exception e) {// do nothing}if (stmtMetaObj.hasGetter("delegate")) {//Hikaritry {statement = (Statement) stmtMetaObj.getValue("delegate");} catch (Exception ignored) {}}String originalSql = null;String stmtClassName = statement.getClass().getName();if (DRUID_POOLED_PREPARED_STATEMENT.equals(stmtClassName)) {try {if (druidGetSqlMethod == null) {Class<?> clazz = Class.forName(DRUID_POOLED_PREPARED_STATEMENT);druidGetSqlMethod = clazz.getMethod("getSql");}Object stmtSql = druidGetSqlMethod.invoke(statement);if (stmtSql instanceof String) {originalSql = (String) stmtSql;}} catch (Exception e) {e.printStackTrace();}} else if (T4C_PREPARED_STATEMENT.equals(stmtClassName)|| ORACLE_PREPARED_STATEMENT_WRAPPER.equals(stmtClassName)) {try {if (oracleGetOriginalSqlMethod != null) {Object stmtSql = oracleGetOriginalSqlMethod.invoke(statement);if (stmtSql instanceof String) {originalSql = (String) stmtSql;}} else {Class<?> clazz = Class.forName(stmtClassName);oracleGetOriginalSqlMethod = getMethodRegular(clazz, "getOriginalSql");if (oracleGetOriginalSqlMethod != null) {//OraclePreparedStatementWrapper is not a public class, need set this.oracleGetOriginalSqlMethod.setAccessible(true);if (null != oracleGetOriginalSqlMethod) {Object stmtSql = oracleGetOriginalSqlMethod.invoke(statement);if (stmtSql instanceof String) {originalSql = (String) stmtSql;}}}}} catch (Exception e) {//ignore}}if (originalSql == null) {originalSql = statement.toString();}originalSql = originalSql.replaceAll("[\\s]+", StringPool.SPACE);int index = indexOfSqlStart(originalSql);if (index > 0) {originalSql = originalSql.substring(index);}// 计算执行 SQL 耗时long start = SystemClock.now();Object result = invocation.proceed();long timing = SystemClock.now() - start;// SQL 打印执行结果Object target = PluginUtils.realTarget(invocation.getTarget());MetaObject metaObject = SystemMetaObject.forObject(target);MappedStatement ms = (MappedStatement) metaObject.getValue("delegate.mappedStatement");// 打印 sqlSystem.err.println(StringUtil.format("\n==============  Sql Start  ==============" +"\nExecute ID  :{}" +"\nExecute SQL :{}" +"\nExecute Time:{} ms" +"\n==============  Sql  End   ==============\n",ms.getId(), originalSql, timing));return result;}@Overridepublic Object plugin(Object target) {if (target instanceof StatementHandler) {return Plugin.wrap(target, this);}return target;}/*** 获取此方法名的具体 Method** @param clazz      class 对象* @param methodName 方法名* @return 方法*/private Method getMethodRegular(Class<?> clazz, String methodName) {if (Object.class.equals(clazz)) {return null;}for (Method method : clazz.getDeclaredMethods()) {if (method.getName().equals(methodName)) {return method;}}return getMethodRegular(clazz.getSuperclass(), methodName);}/*** 获取sql语句开头部分** @param sql ignore* @return ignore*/private int indexOfSqlStart(String sql) {String upperCaseSql = sql.toUpperCase();Set<Integer> set = new HashSet<>();set.add(upperCaseSql.indexOf("SELECT "));set.add(upperCaseSql.indexOf("UPDATE "));set.add(upperCaseSql.indexOf("INSERT "));set.add(upperCaseSql.indexOf("DELETE "));set.remove(-1);if (CollectionUtils.isEmpty(set)) {return -1;}List<Integer> list = new ArrayList<>(set);list.sort(Comparator.naturalOrder());return list.get(0);}}

在MybatisPlusConfiguration拦截


package org.springjmis.core.boot.config;import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor;
import lombok.AllArgsConstructor;
import org.mybatis.spring.annotation.MapperScan;
import org.springjmis.core.boot.props.MybatisPlusProperties;
import org.springjmis.core.mp.plugins.SqlLogInterceptor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** mybatisplus 配置** @author Chill*/
@Configuration(proxyBeanMethods = false)
@AllArgsConstructor
@MapperScan("org.springjmis.**.mapper.**")
@EnableConfigurationProperties(MybatisPlusProperties.class)
public class MybatisPlusConfiguration {/*** mybatis-plus 拦截器集合*/@Bean@ConditionalOnMissingBean(MybatisPlusInterceptor.class)public MybatisPlusInterceptor mybatisPlusInterceptor(MybatisPlusProperties mybatisPlusProperties) {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();// 配置分页拦截器PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();paginationInnerInterceptor.setMaxLimit(mybatisPlusProperties.getPageLimit());paginationInnerInterceptor.setOverflow(mybatisPlusProperties.getOverflow());interceptor.addInnerInterceptor(paginationInnerInterceptor);return interceptor;}/*** sql 日志** @return SqlLogInterceptor*/@Bean@ConditionalOnProperty(value = "blade.mybatis-plus.sql-log", matchIfMissing = true)public SqlLogInterceptor sqlLogInterceptor() {return new SqlLogInterceptor();}}

http://www.lryc.cn/news/128244.html

相关文章:

  • C++ STL list
  • Django图书商城系统实战开发-实现订单管理
  • POJ 3421 X-factor Chains 埃氏筛法+质因子分解+DFS
  • 【积水成渊】9 个CSS 伪元素
  • 【002】学习笔记之typescript的【任意类型】
  • 题目:2574.左右元素和的差值
  • 成集云 | 用友U8采购请购单同步钉钉 | 解决方案
  • 爬虫的代理IP池写哪里了?
  • CSS变形与动画(三):animation帧动画详解(用法 + 四个例子)
  • Ubuntu发布java版本
  • Java反射机制是什么?
  • legacy-peer-deps的作用
  • 卷积操作后特征图尺寸,感受野,参数量的计算
  • C/C++ 注意点补充
  • Python实时监控键盘的输入并打印出来
  • LaWGPT零基础部署win10+anaconda
  • 糖尿病视网膜病变,黄斑病变,年龄相关检测研究(Matlab代码)
  • 管理类联考——逻辑——真题篇——按知识分类——汇总篇——一、形式逻辑——选言——相容选言——或——第一节 推结论
  • MySQL数据库——图形化界面工具(DataGrip),SQL(2)-DML(插入、修改和删除数据)
  • 【Git】(五)切换分支
  • LVS集群和nginx负载均衡
  • mysql 03.查询(重点)
  • arcpy读取csv、txt文件
  • Leetcode32 最长有效括号
  • 【Android】Dagger和Hilt新手快速入门
  • phpstorm 推荐插件
  • 在进行自动化测试,遇到验证码的问题,怎么办?
  • C语言刷题训练DAY.6
  • Java进阶篇--数据结构
  • 使用Facebook Pixel 埋点