首页 > 数据库 >Mybatis输出完整Sql - Interceptor

Mybatis输出完整Sql - Interceptor

时间:2024-02-21 11:34:20浏览次数:18  
标签:return proceed sqlDetail param Sql Mybatis Interceptor class String

@Intercepts(
        {
                @Signature(type = Executor.class, method = "query"
                        , args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
                @Signature(type = Executor.class, method = "query"
                        , args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class
                        , CacheKey.class, BoundSql.class}),
                @Signature(type = Executor.class, method = "update"
                        , args = {MappedStatement.class, Object.class}),
        }
)
@Slf4j
public class MybatisSqlLogInterceptor implements Interceptor {


    /**
     * 当语句中某个参数值过长,超过配置的阈值,会显示参数开头及下面的省略号
     */
    private static final String LONG_PARAM_DESC = ".....";
    @Setter
    Supplier<Long> slowSqlThreshold = () -> 1000L;      // NOSONAR
    @Setter
    Supplier<Long> paramLengthLogLimit = () -> 1024L;   // NOSONAR

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object proceed;
        try {
            long start = System.currentTimeMillis();
            proceed = invocation.proceed();
            long costTime = System.currentTimeMillis() - start;
            if (costTime > slowSqlThreshold.get()) {
                SqlDetail sqlDetail = getSqlDetail(invocation);
                log.info("executeSql: {}  pararm:[{}]  methodName:[{}]  rowsNum:[{}]  elapsedTime:{}ms"
                        , sqlDetail.getSql()
                        , sqlDetail.getParam()
                        , sqlDetail.getMethodName()
                        , getReturnRows(proceed)
                        , costTime);
            }
        } catch (Exception exception) {
            SqlDetail sqlDetail = getSqlDetail(invocation);
            log.error("executeSql: {}  pararm:[{}]  methodName:[{}] "
                    , sqlDetail.getSql()
                    , sqlDetail.getParam()
                    , sqlDetail.getMethodName()
                    , exception);
            throw exception;
        }
        return proceed;
    }

    /**
     * 获取SQL语句和参数
     */
    @Nullable
    private SqlDetail getSqlDetail(Invocation invocation) {
        SqlDetail sqlDetail = new SqlDetail();
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        if (null != mappedStatement) {
            String methodLocate = mappedStatement.getId();
            sqlDetail.setMethodName(getMethodName(methodLocate, '.'));
        }
        Object parameter = null;
        if (invocation.getArgs().length > 1) {
            parameter = invocation.getArgs()[1];
        }
        //获取参数
        BoundSql boundSql = mappedStatement.getBoundSql(parameter);
        sqlDetail.setSql(boundSql.getSql());
        Configuration configuration = mappedStatement.getConfiguration();
        Object parameterObject = boundSql.getParameterObject();
        StringBuffer sqlParam = new StringBuffer(128);
        List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
        //参数遍历拼接
        if (parameterObject != null) {
            TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();
            // 如果根据parameterObject.getClass()可以找到对应的类型,则替换
            if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
                String param = ConvertUtil.toString(parameterObject);
                sqlParam.append(param.length() > paramLengthLogLimit.get()
                        ? param.substring(0, paramLengthLogLimit.get().intValue()) + LONG_PARAM_DESC : param);
                sqlDetail.setParam(sqlParam.toString());
            } else {
                MetaObject metaObject = configuration.newMetaObject(parameterObject);
                for (ParameterMapping parameterMapping : parameterMappings) {
                    String propertyName = parameterMapping.getProperty();
                    if (metaObject.hasGetter(propertyName)) {
                        String param = ConvertUtil.toString(metaObject.getValue(propertyName));
                        sqlParam.append(param.length() > paramLengthLogLimit.get()
                                        ? param.substring(0, paramLengthLogLimit.get().intValue()) + LONG_PARAM_DESC
                                        : param)
                                .append(',');
                    }
                    if (boundSql.hasAdditionalParameter(propertyName)) {
                        String param = ConvertUtil.toString(boundSql.getAdditionalParameter(propertyName));
                        sqlParam.append(param.length() > paramLengthLogLimit.get() ?
                                        param.substring(0, paramLengthLogLimit.get().intValue()) + LONG_PARAM_DESC
                                        : param)
                                .append(',');
                    }
                }
            }
            if (sqlParam.length() > 0) {
                sqlDetail.setParam(sqlParam.deleteCharAt(sqlParam.length() - 1).toString());
            }
        }
        return sqlDetail;
    }

    private Integer getReturnRows(Object proceed) {
        if (proceed instanceof Collection) {
            return ((Collection<?>) proceed).size();
        }
        if (proceed instanceof Map) {
            return ((Map) proceed).size();
        }
        if (proceed instanceof Integer) {
            return (Integer) proceed;
        }
        return 0;
    }

    /**
     * 生成MyBatis拦截器代理对象
     **/
    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    /**
     * 设置插件属性
     */
    @Override
    public void setProperties(Properties properties) {
    }

    String getMethodName(String str, char separator) {
        if (str == null || str.length() == 0) {
            return str;
        }
        final int pos = str.lastIndexOf(separator);
        if (pos == -1) {
            return str;
        }
        final int secondPos = str.lastIndexOf(separator, pos - 1);
        if (secondPos == -1) {
            return str;
        }
        return str.substring(secondPos + 1);
    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Accessors(chain = true)
    public static class SqlDetail {
        private String sql;
        private String param;
        private String methodName;
    }
}

标签:return,proceed,sqlDetail,param,Sql,Mybatis,Interceptor,class,String
From: https://www.cnblogs.com/gustavo/p/18024820

相关文章

  • 面试官让我讲讲MySQL三大核心日志实现原理
    本文分享自华为云社区《面试必问|聊聊MySQL三大核心日志的实现原理?》,作者:冰河。MySQL几乎成为互联网行业使用的最多的开源关系型数据库,正因如此,MySQL也成为各大互联网公司面试中必问的数据库,尤其是MySQL中的事务实现机制和三大核心日志的实现原理。今天,我们就重点聊聊MySQL三......
  • powerdesigner 生成mysql脚本,要求字段、表名有注释
    1.字段注释设置:在pdm视图中,Database-->EditCurrentDBMS。   找到MySql5.0-->Script-->Objects-->Column-->Add。a)原来的内容%20:COLUMN%[%National%?national]%DATATYPE%[%Unsigned%?unsigned][%ZeroFill%?zerofill][[.O:[characterset][charset]]%Ch......
  • 系统表不存在执行升级(mysql_upgrade)操作报错误的解决办法(5.6升级到5.7)
    环境:OS:Centos7原db:5.6新db:5.7 执行升级命令报如下错误[root@hadoop-slave1mysql]#/home/middle/mysql57/bin/mysql_upgrade-s-hlocalhost-pyeemiao3040-P13306-S/home/middle/mysql57/data/mysql.sockmysql_upgrade:[Warning]Usingapasswordonthecomma......
  • mysql 数据库安装使用笔记
    1.下面操作的是mysql8.0.20版本免安装版本 2.解压以后CMD管理权限到路径下D:\rujian\mysql-8.0.20-winx64\bin <1>.启动mysql命令:netstartmysql <2>.停止mysql命令:netstopmysql 3.修改初始密码以管理员身份新开cmd,进入mysql安装的bin目录后执行命令:......
  • 若依前后端分离版如何集成的mybatis以及修改集成mybatisplus实现Mybatis增强
    场景若依前后端分离版手把手教你本地搭建环境并运行项目:https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/108465662SpringBoot中使用PageHelper插件实现Mybatis分页:https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/136189442在上面搭建若依前后端分......
  • SQL中为什么不要使用1=1?
    最近看几个老项目的SQL条件中使用了1=1,想想自己也曾经这样写过,略有感触,特别拿出来说道说道。编写SQL语句就像炒菜,每一种调料的使用都会影响菜品的最终味道,每一个SQL条件的加入也会影响查询的执行效率。那么1=1存在什么样的问题呢?为什么又会使用呢?为什么会使用1=1?在动态构建......
  • MySQL
    MySQL创建和删除资料库CREATEDATABASE`sql_tutorial`;#创建资料库SHOWDATABASES;#展示所有资料库DROPDATABASE`sql_tutorial`;#删除资料库每个完整语句后必须加分号创建和删除表格MySQL的一些资料形态:INT整数DECIMAL(3,2)有小数点的数例如2.33......
  • MySQL 8.0 instant 添加和删除列
    MySQL8.0.12开始,以下的altertable操作支持ALGORITHM=INSTANT算法:1.添加新的列。即instantaddcolumn2.添加或者删除虚拟列3.添加或者删除列的默认值4.修改enum、set类型列的定义5.修改索引类型6.重命名表 支持ALGORITHM=INSTANT算法的操作,只会修改数据字......
  • linux下部署MySQL服务
    linux下部署MySQL服务1、安装sudo-s调整为root下用户角色运行以下命令安装MySQL,输入Y继续sudoaptinstallmysql-server2、启动systemctlstartmysqld设置MySQL开机自启动(可选)systemctlenablemysqld3、检查运行状态systemctlstatusmysqld4、配置MySQL用户......
  • MySQL
    库的增删改查(1)语法#增createdatabasedb1;createdatabasedb2charset='gbk'#查showdatabases;#查所有的库showcreatedatabasedb1;#查单个#改alterdatabasedb2charset='utf-8'#删dropdatabasedb2;表的增删改查(1)语法#查看当前所在的库的名字......