【原创】使用更优雅的方式改造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

相关推荐
Victor3561 小时前
MongoDB(52)如何配置分片?
后端
Victor3561 小时前
MongoDB(53)什么是分片键?
后端
百结2147 小时前
Mysql数据库操作
数据库·mysql·oracle
薛定谔的悦8 小时前
MQTT通信协议业务层实现的完整开发流程
java·后端·mqtt·struts
ego.iblacat8 小时前
MySQL 服务基础
数据库·mysql
enjoy嚣士8 小时前
springboot之Exel工具类
java·spring boot·后端·easyexcel·excel工具类
无限大69 小时前
职场逻辑03:3步搞定高效汇报,让领导看到你的价值
后端
alexhilton9 小时前
Compose中的ContentScale:终极可视化指南
android·kotlin·android jetpack
盐水冰9 小时前
【烘焙坊项目】后端搭建(12) - 订单状态定时处理,来单提醒和顾客催单
java·后端·学习
紫丁香9 小时前
AutoGen详解一
后端·python·flask