【原创】使用更优雅的方式改造MyBatisPlus逻辑删除插件

前言

在之前一篇文章中就介绍了如何自己写一个逻辑删除方面的MP自定义插件。

https://blog.csdn.net/DCTANT/article/details/134515180

但是在这篇文章中有个问题,就是如果有些Entity类不需要逻辑删除功能,也就是压根没有del_flag这个字段,那么自动添加了${表别名}.del_flag会导致SQL报错,因此需要一个更优雅的方式解决这个问题。

解决方案

如果有个方法知道哪些类继承了逻辑删除的Base类,说明这些对应的表就存在逻辑删除字段,反之则没有,不需要自动添加逻辑删除的SQL。

还有一点,如果是要与数据库交互的表,那么必然存在@TableName注解,那么我只需要将所有带有@TableName的类全部拿出来,判断其是否继承自逻辑删除的基类,那么问题就能迎刃而解了。

获取所有带有@TableName注解的类

在SpringBoot中Bean的初始化阶段可以使用@PostConstruct注解,当Bean初始化完成就加载到所有@TableName的类。

代码如下所示:

Kotlin 复制代码
@Component
class TableNameProcessor(
    val applicationContext: ApplicationContext
) {

    @PostConstruct
    fun processAnnotatedClasses() {
        // 获取所有带@TableName注解的Bean实例
        val beans = applicationContext.getBeansWithAnnotation(TableName::class.java)
        for ((beanName, entity) in beans) {
            val clazz = entity::class.java
            val tableNameAnnotation = clazz.getAnnotation(TableName::class.java)
            if (tableNameAnnotation == null) {
                continue
            }

            // INFO: Zhouwx: 2026/1/12 获取表名信息
            val tableName = tableNameAnnotation.value
            if (entity::class.isSubclassOf(BaseEntity::class)) {
                // INFO: Zhouwx: 2026/1/12 如果这是BaseEntity的子类,说明是带有逻辑删除的类,否则不需要逻辑删除
                TableLogicDeleteGlobal.tableLogicDeleteMap[tableName] = true
            } else {
                TableLogicDeleteGlobal.tableLogicDeleteMap[tableName] = false
            }
        }
    }
}

使用applicationContext.getBeansWithAnnotation获取所有带指定注解的类。这里获取到的是一个Map,key为bean的名称,value则是对应的Entity类。使用这个Entity对应的class,获取它的TableName注解。

TableName注解获取到后,可以获取到该类对应的表名。并判断这个类是否继承自BaseEntity类(我的这个类就是逻辑删除的基类)。如果是,说明这张表带有逻辑删除,将表名和true信息存入全局的Map中,直接存储在内存中,方便快速调用。

改造MP自定义逻辑删除插件

只需要改造原来类中的getEqualTo方法即可,这是判断的核心。

Kotlin 复制代码
        if (fromItem is Table) {
            val tableName = fromItem.name
            val isLogicDelete = TableLogicDeleteGlobal.tableLogicDeleteMap[tableName] ?: return null

            if (!isLogicDelete) {
                return null
            }

        }

之后就是判断返回的equalsTo是否为null了,如果为null则不需要加上逻辑删除的相关SQL,如果有则加上。

where要加

Kotlin 复制代码
            if (where == null) {
                // INFO: DCT: 2023/11/12 where条件为空,增加一个where,且赋值为 表名.del = 0
                equalsTo?.also {
                    plainSelect.setWhere(equalsTo)
                }
            } else {
                // INFO: DCT: 2023/11/12 普通where,后面直接加上本表的 表名.del = 0
                equalsTo?.also {
                    val andExpression = AndExpression(where, equalsTo)
                    plainSelect.setWhere(andExpression)
                }

                // INFO: DCT: 2023/11/12 有子查询的处理子查询
                handleWhereSubSelect(where)
            }

join也要加

Kotlin 复制代码
        for (join in joins) {
            // INFO: DCT: 2023/11/12 获取表别名,并获取 表.del = 0
            val rightItem = join.getRightItem()
            val equalsTo = getEqualTo(rightItem)
            equalsTo?.also {
                // INFO: DCT: 2023/11/12 获取on右边的表达式
                val onExpression = join.getOnExpression()
                // INFO: DCT: 2023/11/12 给表达式增加 and 表.del = 0
                val andExpression = AndExpression(onExpression, equalsTo)

                val expressions = ArrayList<Expression?>()
                expressions.add(andExpression)
                // INFO: DCT: 2023/11/12 目前的这个表达式就是and后的表达式了,不用再增加原来的表达式,因为这个and表达式已经包含了原表达式所有的内容了
                join.setOnExpressions(expressions)
            }
        }

至此,更加优雅的逻辑删除插件就做好了,相比于前一版更加智能了。

开源代码

相关代码位置在:

https://gitee.com/decentant/onflow-framework/tree/master/onflow-core/src/main/kotlin/com/itdct/onflow/core/mp/logic_delete

相关推荐
上进小菜猪2 小时前
基于 YOLOv8 的太阳能电池片缺陷智能检测识别实战 [目标检测完整源码]
后端
Rysxt_2 小时前
Go语言:现代编程的效率与并发之选
开发语言·后端·golang
鸠摩智首席音效师2 小时前
MySQL ERROR 1114 (HY000): The table is full
数据库·mysql
l***21782 小时前
Spring Boot 整合 log4j2 日志配置教程
spring boot·单元测试·log4j
内存不泄露2 小时前
基于 Spring Boot 的医院预约挂号系统(全端协同)设计与实现
java·vue.js·spring boot·python·flask
Mr -老鬼2 小时前
Rust 知识图-谱基础部分
开发语言·后端·rust
袁慎建@ThoughtWorks2 小时前
如何发布自定义 Spring Boot Starter
java·spring boot·后端
lynn8570_blog2 小时前
关于compose的remember
android·kotlin
IT_陈寒2 小时前
SpringBoot 3.0实战:10个高效开发技巧让你的启动时间减少50%
前端·人工智能·后端