在现代软件开发中,数据持久化层的优化和问题解决是确保应用性能和数据一致性的关键。MybatisPlus,作为Mybatis的增强版本,提供了许多便利功能,包括逻辑删除。然而,逻辑删除与数据库唯一性索引的结合可能会引发一些预料之外的冲突。本文将深入探讨这一问题,并提供一系列解决方案。
1. 理解逻辑删除与唯一性索引
逻辑删除是一种常见的数据处理方式,它通过设置一个标志字段(如deleted)来标记记录是否已被删除,而不是直接从数据库中物理删除数据。这样可以保留历史数据,方便后续审计或数据分析。
唯一性索引则是数据库中用来确保某一列或某几列组合的值的唯一性,防止重复数据的插入。例如,用户表中通常会为username或email列设置唯一性索引。
2. 冲突场景
当一个被逻辑删除的记录仍然占据其唯一性索引的位置时,新数据尝试插入相同值时就会遇到冲突,导致插入失败。例如,如果一个用户的username被逻辑删除后,另一个新用户尝试使用相同的username注册,就会因为唯一性约束而失败。
3. 解决方案
3.1 修改唯一性索引
最直接的方法是在数据库层面修改唯一性索引,使其仅在非逻辑删除的记录上生效。例如,在MySQL中,可以创建一个包含username和del_at字段的复合唯一性索引:
ALTER TABLE users ADD COLUMN del_at datetime NULL DEFAULT 0 COMMENT '删除时间';
ALTER TABLE users ADD UNIQUE INDEX unique_username_deleted(username, del_at) USING BTREE;
这样,当添加修改时根据username与del_at字段进行唯一性校验。在逻辑删除时需要给del_at字段进行赋值,该字段仅用来存储删除操作时的时间。
注意:给del_at字段默认值是为了避免MySQL数据库索引字段中如果有null时可能会导致唯一性索引失效的问题。
3.2 新建MybatisPlus逻辑删除拦截器
新建一个LogicSqlInnerInterceptor,继承JsqlParserSupport并实现MybatisPlus的InnerInterceptor,在beforePrepare方法中处理逻辑删除时自动给del_at字段赋值为当前操作时间。具体代码如下:
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.parser.JsqlParserSupport;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.update.

最低0.47元/天 解锁文章
2631

被折叠的 条评论
为什么被折叠?



