首页 > 数据库 >Mybatis 打印完整的SQL

Mybatis 打印完整的SQL

时间:2024-04-02 15:35:19浏览次数:23  
标签:String SQL org 打印 sql Mybatis import class

1、

c++ \033输出设置

2、

package org.jeecg.config.mybatis;

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
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.Configuration;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.jeecg.common.constant.JeecgConstant;
import org.jeecg.common.util.CN;
import org.springframework.core.Ordered;

import java.lang.reflect.Field;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Properties;

/**
 * <p>
 * 自定义SQL插件,功能如下
 * 1:打印SQL执行时间
 * 2:打印SQL,参数自动设置到SQL中
 * 3:区别慢SQL,SQL执行时间大于5秒的SQL为红色字体,否则为黄色字体,(执行时间可以自定义)
 * </p>
 */
@Intercepts({
        @Signature(type = StatementHandler.class, method = "update", args = {Statement.class}),
        // @Signature(type = StatementHandler.class, method = "query", args = {MappedStatement.class, Statement.class, Object.class, RowBounds.class, ResultHandler.class}),
        // @Signature(type = StatementHandler.class, method = "batch", args = {Statement.class}),
        // @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}),
        @Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class}),

})
@Slf4j
public class MybatisSqlPrintInterceptor implements Interceptor, Ordered {
    private static final Long DEFAULT_TIME_OUT = 5000L;
    private static final ThreadLocal<SimpleDateFormat> SIMPLE_DATE_FORMAT = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"));

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object proceed = invocation.proceed();
        printSql(startTime, invocation);
        return proceed;
    }

    private void printSql(long startTime, Invocation invocation) {
        try {
            if (JeecgConstant.LogClass.getIsPrintSql()) {
                String sql = formatSql(invocation);
                String method = getMethod(invocation);
                long endTime = System.currentTimeMillis();
                long elapsedTime = endTime - startTime;
                String str = String.format("执行时间:%s ms,调用xml方法: %s [执行SQL]:\n%s ", elapsedTime, method, getColorString(sql));
                log.info(JeecgConstant.LogClass.logPre + str);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }

    private String getColorString(String str) {
        //[c++ \033输出设置]https://blog.csdn.net/weixin_45469233/article/details/130100885
        return String.format("\033[33;1m%s\033[0m", str);
    }

    @Override
    public void setProperties(Properties properties) {
        System.out.println("插件配置的信息:" + CN.toJSONString(properties));
    }

    /**
     * 格式化SQL及其参数
     */
    private String formatSql(Invocation invocation) throws Exception {
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        ParameterHandler parameterHandler = statementHandler.getParameterHandler();
        BoundSql boundSql = statementHandler.getBoundSql();
        String sql = boundSql.getSql();
        if (CN.isEmpty(sql)) {
            return "";
        }

        Class<? extends ParameterHandler> parameterHandlerClass = parameterHandler.getClass();
        Field mappedStatementField = parameterHandlerClass.getDeclaredField("mappedStatement");
        mappedStatementField.setAccessible(true);
        MappedStatement mappedStatement = (MappedStatement) mappedStatementField.get(parameterHandler);

        // 美化sql
        // sql = beautifySql(sql).toLowerCase();

        // 不传参数的场景,直接把Sql美化一下返回出去
        // Object parameterObject = parameterHandler.getParameterObject();
        // List<ParameterMapping> parameterMappingList = boundSql.getParameterMappings();
        // if (Objects.isNull(parameterObject) || parameterMappingList.isEmpty()) {
        //     return sql;
        // }

        // 定义一个没有替换过占位符的sql,用于出异常时返回
        String sqlWithoutReplacePlaceholder = sql;

        try {
            sql = handleCommonParameter(boundSql, mappedStatement);
        } catch (Exception e) {
            System.err.println(JeecgConstant.LogClass.logPre + "[handleCommonParameter]" + e.getMessage());
            // 占位符替换过程中出现异常,则返回没有替换过占位符但是格式美化过的sql
            return sqlWithoutReplacePlaceholder;
        }
        String sql1 = beautifySql(sql);
        return sql1;
    }

    /**
     * 替换SQL中的?,设置sql参数
     */
    private String handleCommonParameter(BoundSql boundSql, MappedStatement mappedStatement) {
        String sql = boundSql.getSql();
        Object parameterObject = boundSql.getParameterObject();
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        Configuration configuration = mappedStatement.getConfiguration();
        TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();

        for (ParameterMapping parameterMapping : parameterMappings) {
            if (parameterMapping.getMode() != ParameterMode.OUT) {
                Object value;
                String propertyName = parameterMapping.getProperty();
                if (boundSql.hasAdditionalParameter(propertyName)) {
                    value = boundSql.getAdditionalParameter(propertyName);
                } else if (parameterObject == null) {
                    value = null;
                } else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
                    value = parameterObject;
                } else {
                    MetaObject metaObject = configuration.newMetaObject(parameterObject);
                    value = metaObject.getValue(propertyName);
                }
                sql = replacePlaceholder(sql, value);
            }
        }
        return sql;
    }

    /**
     * 根据不同的propertyValue类型,匹配SQL?的类型并替换值
     */
    private String replacePlaceholder(String sql, Object propertyValue) {
        String value;
        if (Objects.nonNull(propertyValue)) {
            if (propertyValue instanceof String) {
                value = "'" + propertyValue + "'";
            } else if (propertyValue instanceof Date) {
                value = "'" + SIMPLE_DATE_FORMAT.get().format(propertyValue) + "'";
            } else if (propertyValue instanceof LocalDate) {
                value = "'" + SIMPLE_DATE_FORMAT.get().format((LocalDate) propertyValue) + "'";
            } else {
                value = propertyValue.toString();
            }
        } else {
            value = "null";
        }
        return sql.replaceFirst("\\?", value);
    }

    /**
     * 根据不同的超时时间打印不同颜色的字体,若超时时间大于默认的超时时间,打印红色字体,否则打印黄色字体
     */
    private void printColorString(String str, Long timeOut) {
        if (timeOut < DEFAULT_TIME_OUT) {
            log.info(JeecgConstant.LogClass.logPre + "\033[33;4m" + str + "\033[0m");
        } else {
            log.info(JeecgConstant.LogClass.logPre + "\033[33;4m" + str + "\033[0m");
        }
    }

    private String beautifySql(String sql) {
        sql = sql.replaceAll("[\\s\n ]+", " ");
        return sql;
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    private String getMethod(Invocation invocation) throws Exception {
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        ParameterHandler parameterHandler = statementHandler.getParameterHandler();
        // BoundSql boundSql = statementHandler.getBoundSql();

        Class<? extends ParameterHandler> parameterHandlerClass = parameterHandler.getClass();
        Field mappedStatementField = parameterHandlerClass.getDeclaredField("mappedStatement");
        mappedStatementField.setAccessible(true);
        MappedStatement mappedStatement = (MappedStatement) mappedStatementField.get(parameterHandler);
        return mappedStatement.getId();
    }

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }
}

标签:String,SQL,org,打印,sql,Mybatis,import,class
From: https://www.cnblogs.com/kikyoqiang/p/18110673

相关文章

  • MySQL分组查询实例
    DDL——学生表——成绩表CREATETABLE`student`(`id`int(11)NOTNULLAUTO_INCREMENTCOMMENT'学号',`createDate`datetimeDEFAULTNULL,`userName`varchar(20)DEFAULTNULL,`pwd`varchar(36)DEFAULTNULL,`phone`varchar(11)DEFAULTNULL,`ag......
  • 【附源码】计算机毕业设计银行资金账户管理系统(java+springboot+mysql+mybatis+论文)
    本系统(程序+源码)带文档lw万字以上  文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义银行资金账户管理系统是一种基于互联网技术的信息化管理平台,旨在提高银行资金管理的效率和安全性。随着金融市场的快速发展和金融产品的多样化,银行资金管理面临着......
  • 【附源码】计算机毕业设计疫情居家隔离服务系统(java+springboot+mysql+mybatis+论文)
    本系统(程序+源码)带文档lw万字以上  文末可领取本课题的JAVA源码参考系统程序文件列表系统的选题背景和意义随着新冠疫情的爆发,居家隔离成为了防控疫情的重要手段之一。然而,在实际操作中,居家隔离存在着许多问题,如隔离人员的生活保障、健康状况监测等。因此,设计并实现一个......
  • MyBatisPlus
    MyBatisPlus快速入门使用第三方组件:导入对应的依赖研究依赖如何配置代码如何编写提高扩展技术能力步骤创建数据库编写项目,初始化项目使用springboot初始化导入依赖连接数据库传统方式:pojo--dao(mybatis,mapper.xml)--service--controller使用了myb......
  • MySQL主从同步延迟Seconds_Behind_Master很大
    1.mysql> showslavestatus\G  查看延迟6天多,也是很神奇了2.查看 Master_Log_File和Relay_Master_Log_File对比,可以说明中继日志差100多位置,所有定位是中继日志问题 3.查看中继日志文件,密密麻麻的relay-bin文件 4.查看优化配置mysql>showvariableslike'%......
  • Windows10基于docker的mysql8的备份和拷贝文件到宿主机
    Windows10基于docker的mysql8的备份和拷贝文件到宿主机##环境说明操作系统:windows10docker:v4.25.0mysql:8##进入容器dockerexec-itmysql8/bin/bash ##备份特定数据库mysqldump-uroot-pMm123456jeesite>jeesite.sql ##退出容器 exit ##将备份......
  • postgresql主从部署、pgpool代理中间件部署
    目录一、安装postgresql准备工作1.配置节点间postgres普通用户免密登录2.执行初始化脚本二、主从部署1.master执行2.slave执行三、查看主从数据库状态1.master执行2.slave执行五、配置pgpool中间件1.编译安装pgpool2.配置准备3.启动服务六、pgsql定时备份和监控shell脚本1.pgsql定......
  • MySQL分组查询实例
    DDL——学生表——成绩表CREATETABLE`result`(`rid`int(11)NOTNULLAUTO_INCREMENTCOMMENT'成绩编号',`testName`varchar(255)DEFAULTNULLCOMMENT'测试名称',`score`double(4,2)DEFAULTNULLCOMMENT'成绩',`studentId`int(11)DEFAU......
  • MySQL分组查询实例
    1、DDL——学生表——成绩表CREATETABLE`result`(`rid`int(11)NOTNULLAUTO_INCREMENTCOMMENT'成绩编号',`testName`varchar(255)DEFAULTNULLCOMMENT'测试名称',`score`double(4,2)DEFAULTNULLCOMMENT'成绩',`studentId`int(11)DEF......
  • MySQL分组查询实例
    DDL——学生表——成绩表CREATETABLE`student`(`id`int(11)NOTNULLAUTO_INCREMENTCOMMENT'学号',`createDate`datetimeDEFAULTNULL,`userName`varchar(20)DEFAULTNULL,`pwd`varchar(36)DEFAULTNULL,`phone`varchar(11)DEFAULTNULL,`ag......