如何将完整的sql打在控制台和日志上

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 如何将完整的sql打在控制台和日志上

数据库:sqlserver

项目:springboot

开发工具:idea

第一种:IDEA插件

修改配置application.properties

mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

settings->Plugins->Marketplace 搜索 Mybatis Log

在Debug控制台右键

效果

第二种 拦截器

package com.croot.rims.comm.config;

import com.croot.rims.service.SubsidyService;
import io.seata.common.util.CollectionUtils;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
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.session.RowBounds;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;


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

@Component
@Intercepts({
        @Signature(type = Executor.class, method = "update", args = {
                MappedStatement.class, Object.class }),
        @Signature(type = Executor.class, method = "query", args = {
                MappedStatement.class, Object.class, RowBounds.class,
                ResultHandler.class }) })
@SuppressWarnings({"unchecked", "rawtypes"})
public class MybatisInterceptor implements Interceptor {

    private static final Logger logger = LoggerFactory.getLogger(SubsidyService.class);
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        try{
            MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
            // 获取xml中的一个select/update/insert/delete节点,主要描述的是一条SQL语句
            Object parameter = null;
            // 获取参数,if语句成立,表示sql语句有参数,参数格式是map形式
            if (invocation.getArgs().length > 1) {
                parameter = invocation.getArgs()[1];
                System.out.println("parameter = " + parameter);
                logger.info("parameter = " + parameter);
            }
            String sqlId = mappedStatement.getId(); // 获取到节点的id,即sql语句的id
            System.out.println("sqlId = " + sqlId);
            BoundSql boundSql = mappedStatement.getBoundSql(parameter);  // BoundSql就是封装myBatis最终产生的sql类
            Configuration configuration = mappedStatement.getConfiguration();  // 获取节点的配置
            String sql = getSql(configuration, boundSql, sqlId); // 获取到最终的sql语句
            System.out.println("sql = " + sql);
            logger.info("sql:"+sql);
            logger.error("sql:"+sql);
        }catch(Exception e){
            logger.info(e.getMessage(), e);
        }
        return invocation.proceed();  // 执行完上面的任务后,不改变原有的sql执行过程
    }
// 封装了一下sql语句,使得结果返回完整xml路径下的sql语句节点id + sql语句
    public static String getSql(Configuration configuration, BoundSql boundSql,String sqlId) {
        String sql = showSql(configuration, boundSql);
        StringBuilder str = new StringBuilder(100);
        str.append(sqlId);
        str.append(":");
        str.append(sql);
        return str.toString();
    }
/*<br>    *如果参数是String,则添加单引号, 如果是日期,则转换为时间格式器并加单引号; 对参数是null和不是null的情况作了处理<br>  */
    private static String getParameterValue(Object obj) {
        String value = null;
        if (obj instanceof String) {
            value = "'" + obj.toString() + "'";
        } else if (obj instanceof Date) {
            DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);
            value = "'" + formatter.format(new Date()) + "'";
        } else {
            if (obj != null) {
                value = obj.toString();
            } else {
                value = "";
            }

        }
        return value;
    }
// 进行?的替换
    public static String showSql(Configuration configuration, BoundSql boundSql) {
        Object parameterObject = boundSql.getParameterObject();  // 获取参数
        List<ParameterMapping> parameterMappings = boundSql
                .getParameterMappings();
        String sql = boundSql.getSql().replaceAll("[\\s]+", " ");  // sql语句中多个空格都用一个空格代替
        if (CollectionUtils.isNotEmpty(parameterMappings) && parameterObject != null) {
            TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry(); // 获取类型处理器注册器,类型处理器的功能是进行java类型和数据库类型的转换<br>       // 如果根据parameterObject.getClass()可以找到对应的类型,则替换
            if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
                sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(getParameterValue(parameterObject)));

            } else {
                MetaObject metaObject = configuration.newMetaObject(parameterObject);// MetaObject主要是封装了originalObject对象,提供了get和set的方法用于获取和设置originalObject的属性值,主要支持对JavaBean、Collection、Map三种类型对象的操作
                for (ParameterMapping parameterMapping : parameterMappings) {
                    String propertyName = parameterMapping.getProperty();
                    if (metaObject.hasGetter(propertyName)) {
                        Object obj = metaObject.getValue(propertyName);
                        sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(getParameterValue(obj)));
                    } else if (boundSql.hasAdditionalParameter(propertyName)) {
                        Object obj = boundSql.getAdditionalParameter(propertyName);  // 该分支是动态sql
                        sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(getParameterValue(obj)));
                    }else{sql=sql.replaceFirst("\\?","缺失");}//打印出缺失,提醒该参数缺失并防止错位
                }
            }
        }
        return sql;
    }

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

    @Override
    public void setProperties(Properties properties) {

    }
}

mysql

以上方案mysql也可以,另外Mysql还可以如下修改打印完整sql

jdbc.url=jdbc:mysql://127.0.0.1/test?useUnicode=true&characterEncoding=UTF-8&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&logger=com.mysql.jdbc.log.Slf4JLogger&profileSQL=true


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
17天前
|
SQL 关系型数据库 MySQL
MySQL数据库——索引(3)-索引语法(创建索引、查看索引、删除索引、案例演示),SQL性能分析(SQL执行频率,慢查询日志)
MySQL数据库——索引(3)-索引语法(创建索引、查看索引、删除索引、案例演示),SQL性能分析(SQL执行频率,慢查询日志)
18 2
|
1月前
|
iOS开发
XCode控制台调试无法看到函数跟踪或无法看到输出的日志问题及解决方案
XCode控制台调试无法看到函数跟踪或无法看到输出的日志问题及解决方案
31 0
|
1月前
|
SQL 缓存 关系型数据库
日志系统:一条SQL更新语句是如何执行的?
本文探讨了MySQL中更新语句的执行流程和日志系统,包括redo log(重做日志)和binlog(归档日志)的作用。更新语句会经过连接器、分析器、优化器和执行器,同时涉及redo log和binlog以确保数据的安全性和一致性。redo log用于快速更新并保证crash-safe,采用Write-Ahead Logging策略,先写入redo log再更新磁盘。binlog则是逻辑日志,用于归档和数据恢复。两阶段提交保证redo log和binlog的一致性。文章还提到,定期全量备份的频率影响数据库系统的恢复能力和数据安全性。
17 0
日志系统:一条SQL更新语句是如何执行的?
|
1月前
|
Java 应用服务中间件
解决IDEA tomcat控制台只有server日志
请注意,确保在调试或开发阶段使用更详细的日志级别(如 `DEBUG`或 `TRACE`),但在生产环境中应将其设置为更高的级别以减少日志量。
30 0
|
SQL 数据库 数据安全/隐私保护
sql server 高可用日志传送
原文:sql server 高可用日志传送 一. 日志传送概述     SQL Server使用日志传送,可以自动将主服务器的事务日志备份发送到一个或多个辅助数据库上。可选的监视服务器,记录备份和还原操作的历史记录及状态。
983 0
|
SQL 监控 数据库
SQL Server高可用——日志传送(4-2)——部署
原文: SQL Server高可用——日志传送(4-2)——部署   前文再续,书接上一回。本章演示一下日志传送的具体过程   准备工作:   由于时间关系,已经装好了3台虚拟机,且同在一个域里面:         SQL01:主服务器 SQL02:辅助服务器 SQL03:监视服务器   初始配置:       这里是实验方便,正式环境应该由于特殊账号的读写权限。
1256 0
|
SQL 存储 监控
SQL Server高可用——日志传送(4-3)——使用
原文: SQL Server高可用——日志传送(4-3)——使用   顺接上一篇:SQL Server高可用——日志传送(4-2)——部署 本文为本系列最重要的一篇,讲述如何使用日志传送及一些注意事项。
1146 0
|
5天前
|
SQL IDE Java
Java连接SQL Server数据库的详细操作流程
Java连接SQL Server数据库的详细操作流程
|
13天前
|
SQL DataWorks NoSQL
DataWorks产品使用合集之如何将SQL Server中的数据转存到MongoDB
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
241 1
|
1月前
|
SQL API 流计算
实时计算 Flink版产品使用合集之在Mac M1下的Docker环境中开启SQL Server代理的操作步骤是什么
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
161 1

热门文章

最新文章