mybatisPlus beforeGetBoundSql和setProperties使用场景介绍及代码示例

beforeGetBoundSql 和 setProperties 都是 InnerInterceptor 接口中定义的默认方法,可以用于自定义拦截器实现。

beforeGetBoundSql 方法会在 MyBatis 获取 BoundSql 对象之前被调用,可以通过该方法来修改或扩展 SQL 语句,例如添加或删除条件、修改表名等。常见的使用场景包括:

数据权限控制:在查询数据时,自动添加当前用户可访问的数据范围的 WHERE 条件。
多租户支持:在查询数据时,自动添加租户 ID 的 WHERE 条件,以区分不同租户的数据。
动态表名:根据不同的请求参数,动态修改 SQL 语句中的表名,以实现数据分片或数据隔离等功能。

需要注意的是,修改 BoundSql 对象时,需要使用 MetaObject 对象来操作属性,以保证 MyBatis 的内部状态正确。

setProperties 方法会在创建拦截器实例时被调用,可以用于初始化拦截器的属性或资源,例如加密算法、缓存对象等。常见的使用场景包括:

加密解密:对数据库中的敏感数据进行加密,查询数据时进行解密。
缓存优化:通过缓存某些查询结果来提高系统性能,可以将缓存对象作为拦截器的属性来管理。
数据库连接池:创建数据库连接池对象并缓存起来,减少每次请求时创建连接池的开销。

需要注意的是,setProperties 方法中的参数 Properties 是一个键值对集合,可以通过该对象获取配置文件中定义的属性值。在编写拦截器时,需要定义对应的属性,并在 setProperties 方法中将其赋值给拦截器的成员变量。

代码示例:
beforeGetBoundSql 和 setProperties 两个方法都是 InnerInterceptor 接口中定义的默认方法,下面分别介绍其作用和示例代码。

在 MyBatis 中,BoundSql 对象表示了一个 SQL 语句的信息,包括 SQL 语句本身和它所需要的参数。在执行 SQL 之前,MyBatis 会通过解析 XML 配置文件和 Mapper 接口,生成对应的 BoundSql 对象。

beforeGetBoundSql 方法允许开发者在获取 BoundSql 对象之前进行必要的操作,例如设置参数、修改 SQL 等。下面是一个示例代码:

public class MyInterceptor implements InnerInterceptor {@Overridepublic void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {// 获取原始的 SQL 语句String sql = boundSql.getSql();// 对 SQL 语句进行修改,添加 WHERE 条件if (!sql.contains("WHERE")) {sql += " WHERE deleted = 0";}// 将修改后的 SQL 语句设置回去MetaObject metaObject = SystemMetaObject.forObject(boundSql);metaObject.setValue("sql", sql);}@Overridepublic void setProperties(Properties properties) {// 设置拦截器属性,例如将 deleted 字段从逻辑删除修改为物理删除}
}

在上面的代码中,beforeQuery 方法首先获取原始的 SQL 语句,然后判断是否已经包含了 WHERE 条件,如果没有,就添加一个 WHERE 条件来控制查询的数据范围。最后,再将修改后的 SQL 语句设置回去。

需要注意的是,在修改 BoundSql 对象时,不能直接调用其方法,而是需要通过 MetaObject 对象来操作属性,这样才能保证 MyBatis 的内部状态正确。

setProperties 方法允许开发者在创建拦截器实例时对其进行配置,例如设置一些参数、初始化一些资源等。下面是一个示例代码:

public class MyInterceptor implements InnerInterceptor {private String algorithm; // 加密算法@Overridepublic void beforeUpdate(Executor executor, MappedStatement ms, Object parameter) throws SQLException {// 在更新之前对参数进行加密if (parameter instanceof BaseEntity) {BaseEntity entity = (BaseEntity) parameter;entity.encrypt(algorithm);}}@Overridepublic void setProperties(Properties properties) {// 设置加密算法algorithm = properties.getProperty("algorithm");}
}

在上面的代码中,我们定义了一个成员变量 algorithm,它表示加密算法。在 beforeUpdate 方法中,我们首先判断参数是否为 BaseEntity 类型,如果是,则调用其 encrypt 方法对数据进行加密。在 setProperties 方法中,我们获取配置文件中的 algorithm 属性,并将其设置到拦截器实例的成员变量中,以便在 beforeUpdate 方法中使用。

使用场景一:加密解密

在数据库存储敏感数据时,对数据进行加密,在查询数据时进行解密,保护数据的安全性。

public class EncryptionInterceptor implements InnerInterceptor {private String algorithm; // 加密算法@Overridepublic void beforeGetBoundSql(StatementHandler sh) {// 获取原始的 SQL 语句BoundSql boundSql = sh.getBoundSql();String sql = boundSql.getSql();// 解密 SQL 语句String decryptedSql = decryptSql(sql);// 将解密后的 SQL 语句设置回去MetaObject metaObject = SystemMetaObject.forObject(boundSql);metaObject.setValue("sql", decryptedSql);}@Overridepublic void setProperties(Properties properties) {// 设置加密算法algorithm = properties.getProperty("algorithm");}private String decryptSql(String encryptedSql) {// 解密 SQL 语句// ...}
}

在上述代码中,EncryptionInterceptor 实现了 beforeGetBoundSql 方法,在获取 BoundSql 对象之前,对 SQL 语句进行解密操作。通过 setProperties 方法设置加密算法的属性值。

需要注意的是,这只是示例代码,实际的加密解密操作需要根据具体的加密算法和业务逻辑来编写。

当需要根据条件动态修改 SQL 语句时,可以使用 beforeGetBoundSql 方法。下面是一个场景示例:

使用场景二:
假设有一个用户表 User,包含 id、name、age 等字段。现在需要实现一个分页查询功能,只返回年龄大于 18 岁的用户记录,并且查询结果按照姓名升序排序。但是,由于数据库中存储的是加密后的数据,所以需要在查询之前解密数据,再进行条件过滤和排序操作。

public class DecryptInterceptor implements InnerInterceptor {@Overridepublic void beforeGetBoundSql(StatementHandler sh) {BoundSql boundSql = sh.getBoundSql();String sql = boundSql.getSql();// 解密 SQL 语句String decryptedSql = decryptSql(sql);// 将解密后的 SQL 语句设置回去MetaObject metaObject = SystemMetaObject.forObject(boundSql);metaObject.setValue("sql", decryptedSql);// 设置查询条件Map<String, Object> parameterObject = (Map<String, Object>) boundSql.getParameterObject();parameterObject.put("minAge", 18);// 修改排序方式String originalOrderByClause = boundSql.getOrderByClause();StringBuilder newOrderByClause = new StringBuilder();if (StringUtils.isNotEmpty(originalOrderByClause)) {newOrderByClause.append(originalOrderByClause).append(", ");}newOrderByClause.append("name ASC");metaObject.setValue("orderByClause", newOrderByClause.toString());}private String decryptSql(String sql) {// 解密 SQL 语句// ...}
}

在上述代码中,DecryptInterceptor 实现了 beforeGetBoundSql 方法,在获取 BoundSql 对象之前解密 SQL 语句,并设置查询条件和排序方式。使用 MetaObject 对象操作 BoundSql 对象的属性来实现修改。

需要注意的是,这只是示例代码,实际的加密解密操作需要根据具体的加密算法和业务逻辑来编写。

使用场景三:

当需要在拦截器中使用一些配置信息时,可以使用 setProperties 方法。下面是一个场景示例:

假设有一个需求:需要记录 SQL 执行时间,并根据执行时间判断 SQL 是否过慢。如果 SQL 过慢,需要记录日志并发出告警。为了方便配置告警阈值,可以将告警阈值作为拦截器的属性,在创建拦截器实例时通过配置文件进行配置。

public class SqlExecutionTimeInterceptor implements InnerInterceptor {private long threshold; // 告警阈值,单位毫秒@Overridepublic Object intercept(Invocation invocation) throws Throwable {long startTime = System.currentTimeMillis();Object result = invocation.proceed();long endTime = System.currentTimeMillis();long executionTime = endTime - startTime;if (executionTime >= threshold) {log.warn("SQL 执行时间过长,耗时:{}ms", executionTime);sendAlarm(executionTime);}return result;}@Overridepublic void setProperties(Properties properties) {String thresholdStr = properties.getProperty("threshold");threshold = Long.parseLong(thresholdStr);}private void sendAlarm(long executionTime) {// 发送告警// ...}
}

在上述代码中,SqlExecutionTimeInterceptor 实现了 setProperties 方法,在创建拦截器实例时从配置文件中读取告警阈值,并保存到拦截器的属性中。在拦截器的 intercept 方法中,计算 SQL 执行时间,并判断是否超过告警阈值,如果超过,则发送告警。

需要注意的是,这只是示例代码,实际的告警操作需要根据具体的业务逻辑来编写。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/593737.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

利用Spring Cloud和Java系统设置优化工程项目管理系统源码的二次开发体验

工程项目管理涉及众多环节和角色&#xff0c;如何实现高效协同和信息共享是关键。本文将介绍一个采用先进技术框架的Java版工程项目管理系统&#xff0c;该系统支持前后端分离&#xff0c;功能全面&#xff0c;可满足不同角色的需求。从项目进度图表到施工地图&#xff0c;再到…

不忘初心,聚焦安全 —— 一名码龄15年的老程序员2023总结

2023总结 1. 整体回顾2. 亮点工作3. 未来展望 1. 整体回顾 作为一名码龄超15年的老程序员&#xff0c;虽然2008年就注册了CSDN博客&#xff0c;但是从2020年疫情以来才开始偶尔写写博客&#xff0c;前面两年虽然写了不少&#xff0c;但基本属于自娱自乐&#xff0c;粉丝量和阅…

匿名函数自调用的不同写法

匿名函数自调用&#xff0c;即函数只执行一次 匿名函数自调用一般写法为: (function(){ //具体内容 }() 其他写法如下&#xff1a; !function(){}() function(){}() ~function(){}() 初次外&#xff0c;前面还可以是&#xff1a;&#xff0c;-&#xff0c;*&#xff0c;/

RxJS之fromEvent学习

有情提示&#xff1a; 阅读此博客前&#xff0c;可先阅读博客https://blog.csdn.net/qq_44327851/article/details/135251408对RxJS进行简单的了解。 概念&#xff1a; fromEvent 是 RxJS 中的一个操作符&#xff0c;用于将事件转换为可观察的对象。它的作用是创建一个可观察对…

熔断、隔离、重试、降级、超时、限流,高可用架构流量治理核心策略全掌握

可用性的定义 在探讨高可用架构之前&#xff0c;让我们以 O2 系统为例&#xff0c;解释一下何谓可用性。O2 是腾讯内部的一个广告投放系统&#xff0c;专注于提升投放效率、分析广告效果&#xff0c;拥有自动化广告投放、AIGC 自动化素材生产等多种功能。 其整体架构概览如下&…

Java最新技术介绍和分析 (202305)

说明&#xff1a;本文完成了2023年5月份&#xff0c;当时最新的LTS版本是Java17&#xff0c;本文在撰写时参考了美团技术团队和阿里JDK团队相关的文章&#xff0c;以及本文也引了用文章中的图片。在此表示感谢&#xff01; Java版本火车 相信老牌的Java开发者和爱好者把Java的…

【技巧】IDEA 使用小技巧(三)

IDEA 使用小技巧&#xff08;三&#xff09; 配置目录Ctrl 鼠标方法缩小字体 配置目录 IDEA 在使用的过程中会在 C 盘的用户目录下写入相关配置&#xff0c;目录如下&#xff1a; "C:\Users\个人用户名\AppData\Local\JetBrains" "C:\Users\个人用户名\AppDa…

Java实现限流算法

限流算法是指在分布式系统中控制流量的一种方法。它用于防止系统被过多的请求拥塞而导致性能下降或崩溃。 常见的限流算法有以下几种&#xff1a; 固定窗口算法&#xff08;Fixed Window Algorithm&#xff09;&#xff1a;将时间划分为固定的时间窗口&#xff0c;每个时间窗口…

Halcon顶帽运算与底帽运算的应用

Halcon顶帽运算与底帽运算的应用 文章目录 Halcon顶帽运算与底帽运算的应用1. 提取小的物件2. 校正非均匀光照 正如上文所说的&#xff0c;顶帽运算返回的像素部分是尺寸比结构元素小的&#xff0c;并且比较亮的局部小区域&#xff1b;底帽运算返回的像素部分是尺寸比结构元素小…

打造炫酷粒子效果的前端利器tsParticles

前端潮流速递 &#xff1a;打造炫酷粒子效果的前端利器tsParticles 在现代前端开发中&#xff0c;动画和视觉效果是吸引用户的关键元素之一。而实现炫酷而引人入胜的粒子效果&#xff0c;常常需要耗费大量的时间和精力。然而&#xff0c;有了 tsParticles&#xff0c;这一切变…

找不到pixman_region32_init代码实现的原因

我们在pixman直接查找pixman_region32_init实现会找不到&#xff0c;原因在于PREFIX宏 1、在pixman-region32.c和pixman-region16.c有很大关系&#xff0c;以pixman-region32.c为例 #ifdef HAVE_CONFIG_H #include <pixman-config.h> #endif #include "pixman-priva…

网络安全—PGP8.1软件应用

文章目录 安装PGP8了解工作原理 PGP使用准备工作加密与解密加密者视角&#xff08;发送方&#xff09;接收者视角&#xff08;接收方&#xff09; 签名签名方&#xff08;发送方&#xff09;验证签名方&#xff08;接收方&#xff09; 补充加密签名一段文字签名后的格式 验证解…

Java中关键词strictfp有什么作用?

在Java中&#xff0c;关键词strictfp用于声明一个方法、类或接口是严格遵守浮点数计算规范的。 具体作用包括&#xff1a; 保证浮点数计算的结果在不同平台上是一致的&#xff0c;避免由于浮点数计算的不精确性导致的结果不确定性。 指定了严格的浮点数计算规则&#xff0c;禁…

186.【2023年华为OD机试真题(C卷)】整数编码(JavaPythonC++JS实现)

请到本专栏顶置查阅最新的华为OD机试宝典 点击跳转到本专栏-算法之翼:华为OD机试 🚀你的旅程将在这里启航!本专栏所有题目均包含优质解题思路,高质量解题代码,详细代码讲解,助你深入学习,深度掌握! 文章目录 【2023年华为OD机试真题(C卷)】整数编码(Java&…

K8s 中Pod无法启动5个常见问题总结

一、ImagePullBackOff Kubernetes pod 无法启动的原因之一是运行时无法从注册表中检索容器镜像。换句话说&#xff0c;pod 不会启动&#xff0c;因为至少有一个在清单中指定的容器没有启动。 当 pod 遇到此问题时&#xff0c;kubectl get pods 命令会将 pod 的状态显示为Image…

【解决】Unity 设置跨设备分辨率表现

开发平台&#xff1a;Unity 2018版本以上 开发语言&#xff1a;CSharp 编程平台&#xff1a;Visual Studio 2022   问题描述 使用 UnityEngine.dll 中关于设置分辨率的方法时&#xff0c;无法满足应用以设定分辨率进行屏幕显示问题。因而造成画面不同程度的拉伸情况。而这种情…

机器学习-基于Word2vec搜狐新闻文本分类实验

机器学习-基于Word2vec搜狐新闻文本分类实验 实验介绍 Word2vec是一群用来产生词向量的相关模型&#xff0c;由Google公司在2013年开放。Word2vec可以根据给定的语料库&#xff0c;通过优化后的训练模型快速有效地将一个词语表达成向量形式&#xff0c;为自然语言处理领域的应…

threejs中group下绑定唯一key导致parten丢失的问题

技术架构 reactthreejsreact-three/dreireact-three/fiberuse-gesture/react 场景 一个分组下有一个Line&#xff0c;当使用gesture的useDrag触发事件以后&#xff1a; import { Line } from react-three/drei import { ThreeEvent, useFrame } from react-three/fiber imp…

C# StringBuilder对比string的优点和15大案例

文章目录 StringBuilder和String 对比1. **循环内字符串连接**2. **构建大型日志消息**3. **格式化长字符串**4. **SQL 查询构造**5. **从文件读取并合并行**6. **拼接数组元素**7. **格式化电子邮件模板**8. **处理用户输入流**9. **JSON 或 XML 格式的序列化与构建**10. **动…