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

SQL美化器优化

文章目录

    • 1.目录
    • 2.代码

1.目录

CleanShot 2024-10-26 at 19.26.45@2x

2.代码

package com.sunxiansheng.mybatis.plus.inteceptor;import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.*;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.*;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.github.vertical_blank.sqlformatter.SqlFormatter;
import com.github.vertical_blank.sqlformatter.languages.Dialect;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;import java.sql.Statement;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;/*** SQL美化拦截器:显示完整的SQL,并输出执行结果*/
@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 SqlBeautyInterceptor implements Interceptor {private static final Logger logger = LoggerFactory.getLogger(SqlBeautyInterceptor.class);// ANSI 颜色代码private static final String ANSI_RESET = "\u001B[0m";private static final String ANSI_BRIGHT_GREEN = "\u001B[92m";   // 亮绿色(结果)private static final String ANSI_BRIGHT_BLUE = "\u001B[94m";    // 亮蓝色(项目名称)// Gson 实例,用于格式化结果private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();@Overridepublic Object intercept(Invocation invocation) throws Throwable {StatementHandler statementHandler = (StatementHandler) invocation.getTarget();MetaObject metaObject = SystemMetaObject.forObject(statementHandler);// 分离代理对象链while (metaObject.hasGetter("h")) {Object object = metaObject.getValue("h");metaObject = SystemMetaObject.forObject(object);}// 分离最后一个代理对象的目标类while (metaObject.hasGetter("target")) {Object object = metaObject.getValue("target");metaObject = SystemMetaObject.forObject(object);}MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");BoundSql boundSql = (BoundSql) metaObject.getValue("delegate.boundSql");Configuration configuration = mappedStatement.getConfiguration();long startTime = System.currentTimeMillis();Object result = null;try {// 执行 SQL,获取结果result = invocation.proceed();return result;} finally {long endTime = System.currentTimeMillis();long sqlCost = endTime - startTime;SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();// 使用修改后的 formatSql 方法String formattedSql = formatSql(configuration, boundSql);// 格式化执行结果String formattedResult = formatResult(result, sqlCommandType);// 日志输出logger.info("\n========================\n{}SQL 类型:{} {}{}{}\n{}SQL:{}\n{}{}{}\n{}执行耗时:{} {}{}ms{} \n{}结果:{}\n{}{}\n{}========================{}",ANSI_BRIGHT_BLUE, ANSI_RESET,ANSI_BRIGHT_GREEN, sqlCommandType, ANSI_RESET,ANSI_BRIGHT_BLUE, ANSI_RESET,ANSI_BRIGHT_GREEN, formattedSql, ANSI_RESET,ANSI_BRIGHT_BLUE, ANSI_RESET,ANSI_BRIGHT_GREEN, sqlCost, ANSI_RESET,ANSI_BRIGHT_BLUE, ANSI_RESET,ANSI_BRIGHT_GREEN, formattedResult, ANSI_RESET,ANSI_BRIGHT_BLUE, ANSI_RESET);}}@Overridepublic Object plugin(Object target) {// 使用 Plugin.wrap 生成代理对象return Plugin.wrap(target, this);}@Overridepublic void setProperties(Properties properties) {// 可以通过配置文件设置属性}/*** 格式化 SQL,将参数替换到 SQL 中,并使用 SQLFormatter 进行格式化** @param configuration MyBatis 配置对象* @param boundSql      绑定的 SQL* @return 格式化后的 SQL*/private String formatSql(Configuration configuration, BoundSql boundSql) {try {// 获取 SQL 语句String sql = boundSql.getSql();// 获取参数对象Object parameterObject = boundSql.getParameterObject();// 获取参数映射List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();if (parameterMappings != null && !parameterMappings.isEmpty() && parameterObject != null) {TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();MetaObject metaObject = configuration.newMetaObject(parameterObject);// 替换 SQL 中的参数占位符for (ParameterMapping parameterMapping : parameterMappings) {String propertyName = parameterMapping.getProperty();Object value;if (boundSql.hasAdditionalParameter(propertyName)) {value = boundSql.getAdditionalParameter(propertyName);} else if (metaObject.hasGetter(propertyName)) {value = metaObject.getValue(propertyName);} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {value = parameterObject;} else {value = null;}sql = replaceFirstQuestionMark(sql, getParameterValue(value));}}// 使用 SQLFormatter 格式化 SQLreturn SqlFormatter.of(Dialect.MySql).format(sql);} catch (Exception e) {logger.error("Error formatting SQL: ", e);return boundSql.getSql();}}private String replaceFirstQuestionMark(String sql, String value) {return sql.replaceFirst("\\?", Matcher.quoteReplacement(value));}private String getParameterValue(Object obj) {if (obj == null) {return "null";}if (obj instanceof String) {return "'" + obj + "'";}if (obj instanceof Number) {return obj.toString();}if (obj instanceof java.util.Date || obj instanceof java.sql.Date || obj instanceof java.sql.Timestamp) {return "'" + obj.toString() + "'";}return "'" + obj.toString() + "'";}/*** 格式化 SQL 执行结果** @param result         执行结果* @param sqlCommandType SQL 类型* @return 格式化后的结果字符串*/private String formatResult(Object result, SqlCommandType sqlCommandType) {if (result == null) {return "null";}try {String formattedResult;if (sqlCommandType == SqlCommandType.SELECT) {// 查询语句,结果通常是 ListformattedResult = GSON.toJson(result);} else if (sqlCommandType == SqlCommandType.UPDATE || sqlCommandType == SqlCommandType.DELETE || sqlCommandType == SqlCommandType.INSERT) {// 更新语句,结果是受影响的行数formattedResult = result.toString() + " 行受影响";} else {// 其他类型formattedResult = result.toString();}// 可根据需要限制结果输出长度,避免日志过大int maxLength = 2000;if (formattedResult.length() > maxLength) {formattedResult = formattedResult.substring(0, maxLength) + "... [结果过长,已截断]";}return formattedResult;} catch (Exception e) {logger.error("Error formatting result: ", e);return result.toString();}}
}
http://www.lryc.cn/news/520021.html

相关文章:

  • 我的128天创作之路:回顾与展望
  • 内核配置参数整理
  • SpringBoot整合Easy-es
  • 于交错的路径间:分支结构与逻辑判断的思维协奏
  • Linux之读者写者模型与特殊锁的学习
  • 回溯专题 记录
  • 使用 Python 实现自动化办公(邮件、Excel)
  • 贪心算法笔记
  • Formality:两种等价状态consistency和equality
  • Java Web开发基础:HTML的深度解析与应用
  • 第30章 汇编语言--- 性能优化技巧
  • HTB:Paper[WriteUP]
  • 数据库中的 DDL、DML 和 DCL
  • OKR 极简史及理解
  • 电商项目-基于ElasticSearch实现商品搜索功能(四)
  • TCP封装数据帧
  • 数据结构与算法之二叉树: LeetCode 515. 在每个树行中找最大值 (Ts版)
  • 百度视频搜索架构演进
  • 构造函数的原型原型链
  • nginx反向代理及负载均衡
  • 单片机实物成品-011 火灾监测
  • 使用 Docker 在 Alpine Linux 下部署 Caddy 服务器
  • 每日十题八股-2025年1月12日
  • Python中定位包含特定文本信息的元素
  • uniapp实现H5页面内容居中与两边留白,打造类似微信公众号阅读体验
  • 极品飞车6里的赛道简介
  • SAP推出云端ERP解决方案,加速零售行业数字化转型
  • Python爬虫进阶——案例:模拟bilibili登录)
  • 什么是数据分析?
  • 基于springboot的课程作业管理系统源码(springboot+vue+mysql)