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

news/2025/3/25 20:30:06/

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.ppmy.cn/news/1291541.html

相关文章

LinuxShell

一、 新建用户 在Linux上新建一个用户并赋予超级用户权限&#xff0c;建立家目录并设置默认shell为bash&#xff0c;并设置Linux在输入sudo密码时显示星号。请提交全部命令及输出截图&#xff08;表明完成需求即可&#xff09;。 1.sudo useradd -m ymhs(用户名) 增加用户 2.su…

搜维尔科技:深入研究工作场所人体工程学中的动作捕捉

创造安全舒适的工作环境对于员工的健康和组织的整体成功至关重要。这就是为什么我们很高兴举办有关“在工作场所人体工程学中利用动作捕捉技术”的网络研讨会。 通过利用动作捕捉的力量&#xff0c;组织可以彻底改变工作场所人体工程学的方法。它使您能够根据客观的运动数据进行…

计算机网络—网络搭建NAT内外网映射

使用Windows Server 2003 网络拓扑 Router 外网&#xff1a;NAT IP 网段 192.168.17.0/24内网&#xff1a;仅主机模式 IP 172.16.29.4 Client1&#xff1a;仅主机模式 IP 172.16.29.2 网关 172.16.29.1 Client2&#xff1a;仅主机模式 IP 172.16.29.3 网关 172.16.29.1…

告别低效!轻松创建在线文档,就用这6款协同办公神器!

在线文档协作工具有哪些&#xff1f; 这些下来&#xff0c;国内外陆续诞生了各式各样的在线文档协作工具&#xff0c;供用户挑选的工具非常多&#xff0c;选择一多&#xff0c;难免犯嘀咕&#xff1a;选哪一款在线文档协作工具好&#xff1f; 不用担心&#xff01;在这个回答…

uView LineProgress 线形进度条

展示操作或任务的当前进度&#xff0c;比如上传文件&#xff0c;是一个线形的进度条。 #平台差异说明 App&#xff08;vue&#xff09;App&#xff08;nvue&#xff09;H5小程序√√√√ #基本使用 通过percentage设置当前的进度值&#xff0c;该值区间为0-100.通过activeC…

深度解析HashMap:探秘Java中的键值存储魔法

文章目录 一、 **前言**1.1 介绍HashMap在Java中的重要性1.2 引出本文将深入挖掘HashMap的内部机制 二、 **HashMap的基本概念**2.1 什么是HashMap&#xff1f;2.2 为什么HashMap在Java中如此流行&#xff1f; 三、 **HashMap的内部结构**3.1 数组和链表的结合体&#xff1a;桶…

蜥蜴目标检测数据集VOC格式1400张

蜥蜴&#xff0c;一种爬行动物&#xff0c;以其独特的形态和习性&#xff0c;成为了人们关注的焦点。 蜥蜴的外观多样&#xff0c;体型大小不一。它们通常拥有长条的身体、四肢和尾巴&#xff0c;鳞片覆盖全身&#xff0c;这使得它们能够在各种环境中轻松移动。大多数蜥蜴拥有…

C++八股学习心得.4

1.C 类 & 对象 C 在 C 语言的基础上增加了面向对象编程&#xff0c;C 支持面向对象程序设计。类是 C 的核心特性&#xff0c;通常被称为用户定义的类型。 类用于指定对象的形式&#xff0c;它包含了数据表示法和用于处理数据的方法。类中的数据和方法称为类的成员。函数在…