在很多企业级应用中,数据删除操作通常采用 逻辑删除 的方式,而不是物理删除。逻辑删除指的是通过更新字段(例如 is_deleted
或 status
)来标记数据为删除状态,而不是真的从数据库中删除记录。这样做的好处是保留数据的历史记录,方便后续的数据恢复、审计以及统计。
MyBatis-Plus (MP)提供了强大的 逻辑删除功能 ,使得开发者可以快速实现这一功能。本文将介绍 MyBatis-Plus 如何实现逻辑删除,包括自动填充字段、配置与实现步骤、常见应用场景,并展示如何使用 remove
方法进行逻辑删除,而不是手动通过 update
来修改删除标记。
1. 逻辑删除的必要性
1.1 逻辑删除的定义
逻辑删除 是指通过修改某个字段(如 is_deleted
)的值,将记录标记为已删除,而不是将其从数据库中删除。这种方式不仅保留了数据的完整性,还能避免因误操作导致的数据丢失。
1.2 逻辑删除的优点
- 数据恢复:可以在数据标记为删除后,依然保留数据,便于后期的恢复。
- 历史审计:可以查看被删除记录的历史数据,满足合规性要求。
- 避免数据丢失:比物理删除更安全,可以减少误操作带来的影响。
1.3 适用场景
- 用户账号删除:用户删除账户时,使用逻辑删除标记账户为已删除,便于后续恢复。
- 订单或产品状态管理:删除订单或产品记录时,使用逻辑删除来标记记录而非物理删除。
- 内容管理系统(CMS):在 CMS 中删除文章或评论时,使用逻辑删除来保留数据。
2. MyBatis-Plus 支持的逻辑删除方式
MyBatis-Plus 提供了非常方便的方式来实现逻辑删除,主要依赖于 @TableLogic
注解,标记字段为逻辑删除字段。MyBatis-Plus 会自动处理该字段的值,并在查询时自动排除已删除的记录。
2.1 使用 @TableLogic
注解进行逻辑删除
MyBatis-Plus 提供的 @TableLogic
注解可以标识一个字段为逻辑删除字段。默认情况下,字段值为 0
表示未删除,值为 1
表示已删除。
示例:User
实体类配置
java
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.IdType;
public class User {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
private String name;
private Integer age;
@TableLogic // 逻辑删除字段
private Integer isDeleted;
// Getters and Setters
}
在这个示例中:
@TableLogic
:标识isDeleted
字段为逻辑删除字段。字段值为0
表示未删除,值为1
表示已删除。
2.2 配置逻辑删除字段的值
MyBatis-Plus 默认将 isDeleted
字段值为 0
表示未删除,1
表示已删除。开发者可以自定义逻辑删除的字段值。
自定义逻辑删除值
java
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusPropertiesCustomizer mybatisPlusPropertiesCustomizer() {
return properties -> {
properties.getGlobalConfig().setLogicDeleteValue("1"); // 设置逻辑删除的值为 1
properties.getGlobalConfig().setLogicNotDeleteValue("0"); // 设置未删除的值为 0
};
}
}
在这个配置中,设置了逻辑删除字段的值为 1
表示已删除,0
表示未删除。
3. 使用 remove
方法进行逻辑删除
3.1 remove
方法与逻辑删除
MyBatis-Plus 中的 remove
方法用于删除记录,默认情况下会执行物理删除操作。为了启用 逻辑删除 ,需要通过设置 @TableLogic
注解,并在执行删除操作时,MyBatis-Plus 会自动更新 isDeleted
字段的值,而不是直接删除记录。
示例:remove
方法进行逻辑删除
java
public void logicDeleteUser(Long userId) {
userService.removeById(userId); // 使用 remove 方法进行逻辑删除
}
在这个例子中,removeById
方法会自动更新 isDeleted
字段,而不是直接从数据库中删除记录。
3.2 removeById
的原理
removeById
方法的实现是基于 @TableLogic
注解的字段,通过更新 isDeleted
字段的值来实现逻辑删除。MyBatis-Plus 在执行删除操作时,会自动生成如下 SQL:
sql
UPDATE user SET is_deleted = 1 WHERE id = ?;
该操作将 is_deleted
字段的值更新为 1
,表示该记录已被删除,而不是从数据库中删除该记录。
3.3 查询时排除逻辑删除的记录
MyBatis-Plus 默认会在查询时自动排除逻辑删除的记录,即 isDeleted
字段为 1
的记录不会被返回。
查询时的自动排除
java
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "John");
List<User> users = userService.list(queryWrapper); // 自动排除逻辑删除的记录
在这个查询中,MyBatis-Plus 会自动忽略 isDeleted = 1
的记录,只返回未删除的记录。
4. 示例:逻辑删除字段与查询
4.1 插入数据时的逻辑删除
在插入数据时,isDeleted
字段会默认设置为 0
,表示数据未删除。
java
User user = new User();
user.setName("John");
user.setAge(30);
userService.save(user); // 插入时,isDeleted 默认为 0
4.2 更新数据时的逻辑删除
在更新数据时,可以通过 removeById
方法将某条记录的 isDeleted
字段更新为 1
,表示数据已被逻辑删除。
java
User user = userService.getById(1L);
user.setIsDeleted(1); // 设置为已删除
userService.updateById(user); // 执行更新操作,实际是逻辑删除
4.3 查询时排除逻辑删除的数据
查询时,MyBatis-Plus 会自动过滤掉逻辑删除的记录。你无需显式地排除已删除记录。
java
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "John");
List<User> users = userService.list(queryWrapper); // 自动排除逻辑删除的记录
4.4 查询已删除的记录
如果需要查询已删除的记录,可以通过 QueryWrapper
手动指定查询条件:
java
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("is_deleted", 1); // 查询已删除的记录
List<User> deletedUsers = userService.list(queryWrapper);
5. 总结
- 逻辑删除的必要性:逻辑删除可以保留数据历史,避免数据丢失,适用于需要审计、数据恢复的场景。
- MyBatis-Plus 支持的逻辑删除方式 :通过
@TableLogic
注解,MyBatis-Plus 能够在插入、更新和查询时自动处理逻辑删除字段。 - 实现步骤 :在实体类中使用
@TableLogic
注解标识逻辑删除字段,配置自定义删除值,并实现MetaObjectHandler
来处理字段填充。 - 使用
remove
方法进行逻辑删除 :MyBatis-Plus 的removeById
方法会自动更新isDeleted
字段,实现逻辑删除,而不是物理删除数据。
MyBatis-Plus 的逻辑删除功能简化了数据的删除操作,保留了删除记录的历史数据,确保了应用的数据一致性和安全性。通过合理配置和使用 MyBatis-Plus 的逻辑删除功能,开发者能够更加高效地管理数据,并满足业务需求。 🚀