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

SpringBoot MybatisPlus 打印SQL及参数

SpringBoot MybatisPlus 打印SQL及参数

import java.text.DateFormat;
import lombok.extern.slf4j.Slf4j;

import cn.hutool.core.collection.CollUtil;

import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.regex.Matcher;

import java.sql.Connection;

import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

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.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.type.TypeHandlerRegistry;

/**
 * 拦截预编译语句输出完整SQL
 */
@Slf4j
@Component
@ConditionalOnProperty(prefix = "mybatis-plus", name = "customer-log", havingValue = "true")
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class SqlLogConf implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler handler = (StatementHandler) invocation.getTarget();
        MetaObject object = MetaObject.forObject(handler,
                SystemMetaObject.DEFAULT_OBJECT_FACTORY,
                SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY,
                new DefaultReflectorFactory());
        MappedStatement statement = (MappedStatement) object.getValue("delegate.mappedStatement");
        log.info("SQL执行类: {}", statement.getId());
        log.info("SQL执行类型: {}", statement.getSqlCommandType().toString());

        BoundSql bound = handler.getBoundSql();
        Configuration configuration = statement.getConfiguration();
        String sql = getFullSql(configuration, bound);
        log.info("SQL: {}", sql);

        long start = System.currentTimeMillis();
        Object value = invocation.proceed();
        long end = System.currentTimeMillis();
        log.info("SQL耗时: {}ms", (end - start));
        return value;
    }

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

    @Override
    public void setProperties(Properties properties) {
        // 可以通过MyBatis配置文件或注解传递属性
    }

    public String getFullSql(Configuration conf, BoundSql bound) {
        Object object = bound.getParameterObject();
        List<ParameterMapping> list = bound.getParameterMappings();
        String sql = bound.getSql().replaceAll("[\\s]+", " ").toLowerCase(Locale.ROOT);
        if (CollUtil.isNotEmpty(list) && object != null) {
            TypeHandlerRegistry type = conf.getTypeHandlerRegistry();
            if (type.hasTypeHandler(object.getClass())) {
                sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(getParaValue(object)));
            } else {
                MetaObject meta = conf.newMetaObject(object);
                for (ParameterMapping parameterMapping : list) {
                    String name = parameterMapping.getProperty();
                    if (meta.hasGetter(name)) {
                        Object obj = meta.getValue(name);
                        sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(getParaValue(obj)));
                    } else if (bound.hasAdditionalParameter(name)) {
                        Object obj = bound.getAdditionalParameter(name);
                        sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(getParaValue(obj)));
                    } else {
                        sql = sql.replaceFirst("\\?", "缺失");
                    }
                }
            }
        }
        return sql;
    }

    private String getParaValue(Object obj) {
        if (obj instanceof String) {
            return "'" + obj + "'";
        } else if (obj instanceof Date) {
            DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);
            return "'" + formatter.format(new Date()) + "'";
        } else {
            if (obj != null) {
                return obj.toString();
            } else {
                return "";
            }
        }
    }

}



http://www.kler.cn/a/300531.html

相关文章:

  • AUTOSAR从入门到精通-城市NOA(领航辅助驾驶)
  • 如何通过 Apache Airflow 将数据导入 Elasticsearch
  • 《AI赋能光追:开启图形渲染新时代》
  • nuiapp在APP中的.nvue页面中使用webview展示空白的问题
  • 2024年度个人成长与技术洞察总结
  • 基于 Python 的财经数据接口库:AKShare
  • UnLua调用C++函数
  • 单链表的实现(C语言)
  • MongoDB高可用和分片集群知识
  • 火语言RPA流程组件介绍--鼠标拖拽元素
  • Node.js运行环境搭建
  • 算法题:找出1到1亿中“只有一个重复的”自然数
  • Flask中的钩子函数
  • SpringCloud之配置中心svn示例和refresh
  • go-mciro系列(四)使用nacos作为配置中心_go使用nacos
  • 【无人机设计与控制】固定翼四旋翼无人机UAV俯仰姿态飞行模糊自整定PID控制Simulink建模
  • 大模型的实践应用29-大语言模型的RLHF(人类反馈强化学习)的具体应用与原理介绍
  • 分布式集群下如何做到唯一序列号
  • rhel 8.6 开箱基本设置
  • Python3网络爬虫开发实战(14)资讯类页面智能解析
  • 【大数据算法】一文掌握大数据算法之:空间亚线性算法。
  • windows和linux安装mysql5.7.31保姆级教程
  • C/C++程序的内存开辟
  • MySQL数据库 — Explain命令
  • hadoop分布式搭建
  • 贪心算法day29|134. 加油站(理解有难度)、135. 分发糖果、860. 柠檬水找零、406. 根据身高重建队列