# MyBatis-Plus教程 - 10 逻辑删除
什么是逻辑删除?
物理删除 :删除数据的时候,是从数据库中直接删除数据;
逻辑删除 :删除数据的时候,没有从数据库删除数据,而是一列数据来标识数据被删除了,例如表中定义一个字段叫
deleted
,值为0表示数据有效,值为1表示数据已经被删除。
逻辑删除利于数据的恢复,但是会长期保留大量数据,查询的时候也需要过滤掉这些数据,对于带有唯一性约束的字段,逻辑删除的记录仍然存在,可能会影响插入新数据。使用的时候需要权衡利弊。
# 10.1 实现逻辑删除
下面看一下在 MyBatis-Plus 中如何实现逻辑删除。
# 1 数据库表添加字段
先给数据库表添加一个用于标识逻辑删除的字段,我这里起名叫 deleted
,名字自定义。
ALTER TABLE tb_user
ADD COLUMN deleted TINYINT(1) DEFAULT 0;
2
并设置默认值为0,表示没有被删除。
# 2 修改pojo
修改数据库表对应的实体类,添加 @TableLogic
注解,标识是用于逻辑删除的字段。
User.java
package com.foooor.helloplus.pojo;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import java.util.Date;
@Data
@TableName("tb_user")
public class User {
// ...其他属性,略
@TableLogic(value="0",delval="1")
private Integer deleted;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
在实体类中添加与数据库对应的属性,并添加 @TableLogic
注解,使用 value
表示没有被删除时候的值,delval
表示被删除后的值。
在配置了 @TableLogic
注解后,MyBatis-Plus 会自动处理以下几种情况:
- 查询:自动过滤掉
deleted = 1
的记录,除非你明确指定要查询被逻辑删除的数据。 - 删除:执行删除操作时,并不会真正删除记录,而是将
deleted
字段设置为1
。 - 更新:更新操作也会自动过滤掉被逻辑删除的记录。
# 3 测试
下面测试一下删除。
通过用户名删除用户。
LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
// 1.设置查询条件
updateWrapper.eq(User::getUsername, "niubi");
// 2.执行删除操作
int result = userMapper.delete(updateWrapper);
log.info("执行结果:{}", result);
2
3
4
5
6
7
执行如下:
可以看到执行的是更新操作,更新了 deleted
字段的值,不是删除。
# 10.2 全局配置
逻辑删除还可以在全局配置。
# 1 全局配置
在 SpringBoot 项目的 application.yaml 中配置全局的逻辑删除。
# mybaits-plus配置
mybatis-plus:
global-config:
db-config:
logic-delete-field: deleted # 逻辑删除字段名(对应数据库中的列名)
logic-not-delete-value: 0 # 表示未删除的值
logic-delete-value: 1 # 表示已删除的值
2
3
4
5
6
7
通过配置全局逻辑删除,那么实体类上的 deleted
属性只需要添加 @TableLogic
注解,不用写 (value="0",delval="1")
。
public class User {
// ...其他属性,略
@TableLogic
private Integer deleted;
}
2
3
4
5
6
# 2 逻辑删除后的查询
被逻辑删除的数据,使用 QueryWrapper 进行查询的时候,是不会被查询出来的。
举个栗子,根据用户名来查询:
// 1.创建条件对象
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
// 2.设置条件
queryWrapper.eq(User::getUsername, "niubi");
// 3.查询
User user = userMapper.selectOne(queryWrapper);
log.info("查询结果:{}", user);
2
3
4
5
6
7
8
9
执行的 SQL 如下:
SELECT id,username,password,age,email,create_time,update_time,deleted FROM tb_user WHERE deleted=0 AND (username = ?)
可以看到查询的时候会自动添加逻辑删除字段的过滤。
**但是需要注意,如果是自己在 Mapper 中定义的查询方法,是不会自动过滤的,需要自己手动过滤的。**这样是非常合理的,否则我们想查询被删除的数据都查询不到。