直接上代码,自己看,粘贴可用
package com.example.demo.mybatis;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ParameterMode;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.ResultHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
/**
* 描述:Sql执行时间记录拦截器 </br>
* 作者:王林冲 </br>
* 时间:2022-12-12 14:11
*/
@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})})
@Component
public class SqlExecuteTimeCountInterceptor implements Interceptor {
private static Logger logger = LoggerFactory.getLogger(SqlExecuteTimeCountInterceptor.class);
/**
* 打印的参数字符串的最大长度
*/
private final static int MAX_PARAM_LENGTH = 50;
/**
* 记录的最大SQL长度
*/
private final static int MAX_SQL_LENGTH = 200;
@Override
public Object intercept(Invocation invocation) throws Throwable {
Object target = invocation.getTarget();
long startTime = System.currentTimeMillis();
StatementHandler statementHandler = (StatementHandler) target;
try {
return invocation.proceed();
} finally {
long endTime = System.currentTimeMillis();
long timeCount = endTime - startTime;
//获取BoundSql
BoundSql boundSql = statementHandler.getBoundSql();
//获取原始sql
String sql = boundSql.getSql();
Object parameterObject = boundSql.getParameterObject();
List<ParameterMapping> parameterMappingList = boundSql.getParameterMappings();
// 格式化Sql语句,去除换行符,替换参数
sql = formatSQL(sql, parameterObject, parameterMappingList);
logger.info("=======> 执行 SQL:{} 执行耗时 {} ms", sql, timeCount);
PluginUtils.MPStatementHandler mpStatementHandler = PluginUtils.mpStatementHandler(statementHandler);
List<String> paramList = handleParameterToStr(mpStatementHandler);
String paramStr = String.join(", ", paramList);
logger.info("=======> 条件参数:{}" ,paramStr );
}
}
private List<Object> handleParameter(PluginUtils.MPStatementHandler mpSh) {
List<Object> values = new ArrayList();
Object parameterObject = mpSh.boundSql().getParameterObject();
List<ParameterMapping> parameterMappings = mpSh.boundSql().getParameterMappings();
if (parameterMappings != null) {
Iterator var5 = parameterMappings.iterator();
while(var5.hasNext()) {
ParameterMapping parameterMapping = (ParameterMapping)var5.next();
if (parameterMapping.getMode() != ParameterMode.OUT) {
String propertyName = parameterMapping.getProperty();
Object value;
if (mpSh.boundSql().hasAdditionalParameter(propertyName)) {
value = mpSh.boundSql().getAdditionalParameter(propertyName);
} else if (parameterObject == null) {
value = null;
} else if (mpSh.configuration().getTypeHandlerRegistry().hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
} else {
MetaObject metaObject = mpSh.configuration().newMetaObject(parameterObject);
value = metaObject.getValue(propertyName);
}
values.add(value);
}
}
}
return values;
}
private List<String> handleParameterToStr(PluginUtils.MPStatementHandler mpSh) {
List<Object> objects = handleParameter(mpSh);
List<String> values = new ArrayList<>(objects.size());
objects.forEach(e -> {
values.add(objToStr(e));
});
return values;
}
private String objToStr (Object o){
StringBuffer sb =new StringBuffer(o.toString());
sb.append("(");
sb.append(o.getClass().getSimpleName()) ;
sb.append(")");
String str = sb.toString();
return str;
}
/**
* 格式化/美化 SQL语句
*
* @param sql sql 语句
* @param parameterObject 参数的Map
* @param parameterMappingList 参数的List
* @return 格式化之后的SQL
*/
private String formatSQL(String sql, Object parameterObject, List<ParameterMapping> parameterMappingList) {
// 输入sql字符串空判断
if (sql == null || sql.length() == 0) {
return "";
}
// 美化sql
sql = beautifySql(sql);
// 不传参数的场景,直接把sql美化一下返回出去
if (parameterObject == null || parameterMappingList == null || parameterMappingList.size() == 0) {
return sql;
}
return LimitSQLLength(sql);
}
/**
* 返回限制长度之后的SQL语句
*
*
* @param sql 原始SQL语句
*/
private String LimitSQLLength(String sql) {
if (sql == null || sql.length() == 0) {
return "";
}
if (sql.length() > MAX_SQL_LENGTH) {
return sql.substring(0, MAX_SQL_LENGTH);
} else {
return sql;
}
}
@Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
}
/**
* 替换SQL 中? 所对应的值, 只保留前50个字符
*
* @param sql sql语句
* @param valueOf ?对应的值
*/
private String replaceValue(String sql, String valueOf) {
//超过50个字符只取前50个
if (valueOf != null && valueOf.length() > MAX_PARAM_LENGTH) {
valueOf = valueOf.substring(0, MAX_PARAM_LENGTH);
}
sql = sql.replaceFirst("\\?", valueOf);
return sql;
}
/**
* 美化sql
*
* @param sql sql语句
*/
private String beautifySql(String sql) {
sql = sql.replaceAll("[\\s\n ]+", " ");
return sql;
}
}
复制
文章转载自IT学习道场,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
相关阅读
SQL优化 - explain查看SQL执行计划(一)
金同学
416次阅读
2025-03-13 16:04:22
云和恩墨钟浪峰:安全生产系列之SQL优化安全操作
墨天轮编辑部
177次阅读
2025-03-31 11:08:20
同一条SQL开发环境比生产环境执行速度快案例分享
董小姐
167次阅读
2025-03-20 06:50:49
GoldenDB数据库SQL画像功能,助力实现精准SQL诊断
Whill
59次阅读
2025-03-28 18:52:43
同事总写烂SQL,于是我出手了...
IT邦德
58次阅读
2025-03-18 06:40:47
让AI读懂Oracle!使用OCI A10微调大模型生成融合查询SQL
甲骨文云技术
56次阅读
2025-03-19 11:21:10
金点分享 | GoldenDB数据库智能SQL限流,让算力精准赋能业务
Whill
54次阅读
2025-03-28 18:53:07
缓存监控治理在游戏业务的实践和探索
vivo互联网技术
39次阅读
2025-03-20 09:51:10
Oracle DBA 必备!这份高效运维的“秘籍”,高频实用 SQL 一网打尽
青年数据库学习互助会
38次阅读
2025-03-31 10:03:00
Oracle数据库常用脚本(七)
lh11811
34次阅读
2025-04-01 08:57:44