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

Springboot + Mybatis 实现sql打印

参照这个视频:https://www.bilibili.com/video/BV1MS411N7mn/?vd_source=90ebeef3261cec486646b6583e9f45f5
实现mybatis对外暴露的接口Interceptor
使用@Intercepts接口,这里的写法参照mybatis-plus中的拦截器写法
在这里插入图片描述

@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}),@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),
})
public class MybatisSqlPrint implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {// 计算这一次SQL执行钱后的时间,统计一下执行耗时long startTime = System.currentTimeMillis();Object proceed = invocation.proceed();long endTime = System.currentTimeMillis();String printSql = null;try {// 通过generateSql方法拿到最终生成的SQLprintSql = generateSql(invocation);}catch (Exception exception){System.err.println(String.format("获取sql异常:%s",exception));}finally {// 拼接日志打印过程long costTime = endTime - startTime;System.out.println(String.format("\n 执行SQL耗时:%dms \n 执行SQL:%s",costTime,printSql));}return proceed;}private static String generateSql(Invocation invocation){// 获取到BoundSql以及Configuration对象// BoundSql 对象存储了一条具体的 SQL 语句及其相关参数信息。// Configuration 对象保存了 MyBatis 框架运行时所有的配置信息MappedStatement statement = (MappedStatement) invocation.getArgs()[0];Object parameter = null;if (invocation.getArgs().length>1){parameter = invocation.getArgs()[1];}Configuration configuration = statement.getConfiguration();BoundSql boundSql = statement.getBoundSql(parameter);// 获取参数对象Object parameterObject = boundSql.getParameterObject();// 获取参数映射List<ParameterMapping> params = boundSql.getParameterMappings();// 获取到执行的SQLString sql = boundSql.getSql();// SQL中多个空格使用一个空格代替sql = sql.replaceAll("[\\s]+", " ");if (!ObjectUtils.isEmpty(params) && !ObjectUtils.isEmpty(parameterObject)){// TypeHandlerRegistry 是 MyBatis 用来管理 TypeHandler 的注册器。TypeHandler 用于在 Java 类型和 JDBC 类型之间进行转换TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();// 如果参数对象的类型有对应的 TypeHandler,则使用 TypeHandler 进行处理if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())){sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(getParameterValue(parameterObject)));}else {// 否则,逐个处理参数映射for (ParameterMapping param : params) {// 获取参数的属性名String propertyName = param.getProperty();MetaObject metaObject = configuration.newMetaObject(parameterObject);// 检查对象中是否存在该属性的 getter 方法,如果存在就取出来进行替换if (metaObject.hasGetter(propertyName)){Object obj = metaObject.getValue(propertyName);sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(getParameterValue(obj)));// 检查 BoundSql 对象中是否存在附加参数。附加参数可能是在动态 SQL 处理中生成的,有的话就进行替换}else if (boundSql.hasAdditionalParameter(propertyName)){Object obj = boundSql.getAdditionalParameter(propertyName);sql = sql.replaceFirst("\\?", Matcher.quoteReplacement(getParameterValue(obj)));}else {// 如果都没有,说明SQL匹配不上,带上“缺失”方便找问题sql = sql.replaceFirst("\\?", "缺失");}}}}return sql;}private static String getParameterValue(Object object) {String value = "";if (object instanceof String){value = "'" + object.toString() + "'";}else if (object instanceof Date){DateFormat format = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);value = "'" + format.format((Date) object) + "'";} else if (!ObjectUtils.isEmpty(object)) {value = object.toString();}return value;}}

最后将拦截器添加到mybatis中

@Configuration
public class MybatisConfig {public MybatisConfig() {System.out.println("MybatisConfig loaded");}SqlSessionFactory sqlSessionFactory;@Autowiredpublic void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {this.sqlSessionFactory = sqlSessionFactory;}@PostConstructpublic void addInterceptor(){sqlSessionFactory.getConfiguration().addInterceptor(new MybatisSqlPrint());}}

实现效果
在这里插入图片描述

相关文章:

Springboot + Mybatis 实现sql打印

参照这个视频&#xff1a;https://www.bilibili.com/video/BV1MS411N7mn/?vd_source90ebeef3261cec486646b6583e9f45f5 实现mybatis对外暴露的接口Interceptor 使用Intercepts接口,这里的写法参照mybatis-plus中的拦截器写法 Intercepts({Signature(type Executor.class, m…...

Cesium默认bing地图数据,还支持哪些地图的数据源呢?

传统的前端开发增长乏力了&#xff0c;新兴的web3D方向前端开发需求旺盛&#xff0c;这一块在国外很成熟&#xff0c;在国内兴起不久&#xff0c; 甚至很多前端老铁都没听过&#xff0c;没见过&#xff0c;没有意识到&#xff0c;前端除了框架、vue、uniapp这些烂大街的&#x…...

高效、智能、安全:小型机房EasyCVR+AI视频综合监控解决方案

一、背景需求分析 随着信息技术的迅猛发展&#xff0c;小型机房在企事业单位中扮演着越来越重要的角色。为了确保机房的安全稳定运行&#xff0c;远程监控成为了必不可少的手段。 二、视频监控 视频监控是机房远程监控的重要组成部分。通过安装IP摄像机及部署视频监控系统Ea…...

数据分析的Excel基础操作

数据透视表 1.先备份&#xff0c;创建原数据副本&#xff0c;将副本sheet隐藏掉。 2.看数据的量级&#xff0c;总行和总列。 3.浏览数据的字段和数值&#xff0c;大致看一下有无异常 4.找到插入->数据透视表&#xff0c;不选择默认点击确认创建&#xff0c;随意点击数据透视…...

【C语言】解决C语言报错:Invalid Pointer

文章目录 简介什么是Invalid PointerInvalid Pointer的常见原因如何检测和调试Invalid Pointer解决Invalid Pointer的最佳实践详细实例解析示例1&#xff1a;未初始化的指针示例2&#xff1a;已释放的指针示例3&#xff1a;返回局部变量的指针示例4&#xff1a;野指针 进一步阅…...

动态图形设计:创造视觉运动的艺术

什么是动态设计&#xff1f;动态设计是一个设计领域&#xff0c;指在用户界面中使用动态效果的设计。简单地说是为了移动用户界面上的元素而设计的。良好的动态设计可以吸引用户的注意&#xff0c;提高用户体验和满意度。动态设计也是界面设计与动态设计的结合&#xff0c;将设…...

CSS 属性 `mix-blend-mode`

CSS 属性 mix-blend-mode 在日常的 Web 开发中,我们大多时候都会使用一些常见的 CSS 属性,比如 font-size、color、background-color 等。但是,CSS 语言中还隐藏着许多鲜为人知但非常强大的属性,今天我们就来探讨其中一个 - mix-blend-mode。 mix-blend-mode 是什么? mix-b…...

三大交易所全面恢复 IPO 申请

6月21日晚间&#xff0c;北交所受理了3家企业的IPO申请&#xff0c;这是北交所时隔3个月之后恢复IPO受理。6月20日晚间&#xff0c;沪深交易所各受理了1家IPO申请&#xff0c;这是沪深交易所时隔半年后再次受理IPO。这也意味着&#xff0c;三大交易所IPO受理全部恢复。 6月21日…...

VC++开发积累——vc++6.0中删除函数的方法,右键,Delete

目录 引出插曲&#xff1a;删除函数的方法多行注释的实现代码输入的自动提示搜索出来&#xff0c;标记和取消标记跳转到上一步的位置 ctrl TAB 总结其他规范和帮助文档创建第一个Qt程序对象树概念信号signal槽slot自定义信号和槽1.自定义信号2.自定义槽3.建立连接4.进行触发 自…...

HBDNY-40/1端子排电压继电器 DC110V 导轨安装 约瑟JOSEF

HBDNY系列端子排型电压电流继电器 系列型号&#xff1a;&#xff08;3、4过/低电压型&#xff0c;5、6过/低电流型&#xff09; HBDNY-30/1端子排型电压继电器&#xff1b;HBDNY-30/2端子排型电压继电器&#xff1b; HBDNY-30/3端子排型电压继电器&#xff1b;HBDNY-30/4端子…...

Redis-数据类型-Geospatial(地理空间索引)

文章目录 1、查看redis是否启动2、通过客户端连接redis3、切换到db5数据库4、将地理位置信息&#xff08;经度和纬度&#xff09;添加到 Redis 的键&#xff08;key&#xff09;中4.1、添加大江商厦4.2、添加西部硅谷 5、升序返回有序集key&#xff0c;让分数一起和值返回的结果…...

Python联动Mysql

首先配置pip源(不然在安装库的时候会很慢!!!) pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/安装必要库: mysql.connector MySQL 连接器/ODBC 是 MySQL ODBC 驱动程序&#xff08;以前称为 MyODBC 驱动程序&#xff09;系列的名称&#xff0c;它使…...

vue3-openlayers 轨迹回放(历史轨迹)(ol-animation-path实现)

本篇介绍一下使用vue3-openlayers轨迹回放&#xff08;历史轨迹&#xff09;&#xff08;ol-animation-path实现&#xff09; 1 需求 轨迹回放&#xff08;历史轨迹&#xff09;实时轨迹 2 分析 轨迹回放&#xff08;历史轨迹&#xff09;&#xff0c;一般是一次性拿到所有…...

计算机视觉全系列实战教程 (十二):图像分割(阈值分割threshold、分水岭算法watershed的使用步骤、洪水填充floodFill算法的使用)

1.图像分割概述 (1)What(什么是图像分割) 将图像划分为不同的子区域&#xff0c;使得同一子区域具有较高的相似性&#xff0c;不同的子区域具有明显的差异性 (2)Why(对图像进行分割有什么作用) 医学领域&#xff1a;将不同组织分割成不同区域帮助分析病情军事领域&#xff…...

Linux的免交互

交互&#xff1a;我们发出指令控制程序的运行&#xff0c;程序在接收到指令之后按照指令的效果做出对应的反应。 免交互&#xff1a;间接的通过第三方的方式把指令传送给程序&#xff0c;不用直接的下达指令。 1、here document免交互 ere document免交互&#xff1a;是命令…...

查看es p12证书文件过期方法

查看证书过期时间: openssl pkcs12 -in elastic-certificates.p12 -nokeys -out elastic-certificates.crt (需要输入证书生成时配置密码) openssl x509 -enddate -noout -in elastic-certificates.crt...

1.8 无符号大数加、减运算

作者 李卫明 单位 杭州电子科技大学 1.8 无符号大数加、减运算。程序设计中经常遇到无符号大数加、减运算问题&#xff0c;请在样例程序Ex1.4基础上实现无符号大数减运算。题目要求输入两个无符号大数&#xff0c;保证一个大数不小于第二个大数&#xff0c;输出它们的和、差。…...

Java常用类--包装类

包装类 一方面出于性能方面的考虑&#xff0c;java为数值使用基本类型&#xff0c;而不是对象。基本类型不是对象层次的组成部分&#xff0c;它们不继承Object。 另一方面有时需要创建表示基本类型的对象&#xff0c;例如集合类只处理对象。为了在类中存储基本类型&#xff0c;…...

SpringMvcの拦截器全局异常处理

一、拦截器 我们在网上发贴子的时候如果没有登录&#xff0c;点击发送按钮会提示未进行登录&#xff0c;跳转到登录页面。这样的功能是如何实现的。 1、 拦截器的作用 Spring MVC 的处理器拦截器类似于Servlet开发中的过滤器Filter&#xff0c;用于对处理器进行预处理和后处理…...

JVM虚拟机的组成

一、为什么要学习 JVM &#xff1f; 1. “ ⾯试造⽕箭&#xff0c;⼯作拧螺丝” &#xff0c; JVM 属于⾯试官特别喜欢提问的知识点&#xff1b; 2. 未来在⼯作场景中&#xff0c;也许你会遇到以下场景&#xff1a; 线上系统突然宕机&#xff0c;系统⽆法访问&#xff0c;甚⾄直…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

JDK 17 新特性

#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持&#xff0c;不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的&#xff…...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...

DingDing机器人群消息推送

文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人&#xff0c;点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置&#xff0c;详见说明文档 成功后&#xff0c;记录Webhook 2 API文档说明 点击设置说明 查看自…...

mac 安装homebrew (nvm 及git)

mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用&#xff1a; 方法一&#xff1a;使用 Homebrew 安装 Git&#xff08;推荐&#xff09; 步骤如下&#xff1a;打开终端&#xff08;Terminal.app&#xff09; 1.安装 Homebrew…...

深入理解Optional:处理空指针异常

1. 使用Optional处理可能为空的集合 在Java开发中&#xff0c;集合判空是一个常见但容易出错的场景。传统方式虽然可行&#xff0c;但存在一些潜在问题&#xff1a; // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...

9-Oracle 23 ai Vector Search 特性 知识准备

很多小伙伴是不是参加了 免费认证课程&#xff08;限时至2025/5/15&#xff09; Oracle AI Vector Search 1Z0-184-25考试&#xff0c;都顺利拿到certified了没。 各行各业的AI 大模型的到来&#xff0c;传统的数据库中的SQL还能不能打&#xff0c;结构化和非结构的话数据如何和…...