一、核心概念
1.1 什么是逻辑删除?
逻辑删除(Soft Delete)是指在数据库中不真正删除记录,而是通过一个字段(如 deleted)标记该记录是否被“删除”。这种方式可以保留数据历史,便于恢复或审计。
与之相对的是物理删除(Hard Delete),即使用 DELETE 语句从数据库中彻底移除记录。
1.2 logic-delete-value 和 logic-not-delete-value
在 MyBatis-Plus 中,这两个配置用于定义逻辑删除字段的取值:
logic-delete-value:表示“已删除”的值(如1)logic-not-delete-value:表示“未删除”的值(如0)
⚠️ 注意:这两个值必须是数据库中实际存储的值类型一致,比如数据库是
TINYINT类型,建议使用整数;如果是VARCHAR,可使用字符串如"Y"/"N"。
二、操作步骤(超详细)
步骤 1:数据库表结构准备
确保你的表中有一个字段用于标识删除状态,通常命名为 deleted 或 is_deleted。
CREATE TABLE user (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
email VARCHAR(100),
deleted TINYINT DEFAULT 0 NOT NULL COMMENT '0:未删除, 1:已删除'
);
字段类型建议使用
TINYINT(1)或INT,避免使用BIT,兼容性更好。
步骤 2:实体类添加 @TableLogic 注解
在实体类中,为逻辑删除字段添加 @TableLogic 注解。
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
@Data
@TableName("user")
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String name;
private String email;
@TableLogic // 标记为逻辑删除字段
private Integer deleted; // 对应数据库中的 deleted 字段
}
✅
@TableLogic注解是启用逻辑删除的关键。
步骤 3:配置 application.yml(Spring Boot 项目)
在 application.yml 中配置逻辑删除的值:
mybatis-plus:
global-config:
db-config:
# 逻辑已删除值(默认为 1)
logic-delete-value: 1
# 逻辑未删除值(默认为 0)
logic-not-delete-value: 0
💡 如果你使用的是
1/0,可以省略此配置(因为这是默认值),但建议显式写出以增强可读性。
步骤 4:启动类或配置类启用 MyBatis-Plus
确保你的 Spring Boot 启动类或配置类启用了 MyBatis-Plus 扫描:
@SpringBootApplication
@MapperScan("com.example.mapper")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
步骤 5:使用 deleteById 或 remove 方法测试
调用删除方法时,MyBatis-Plus 会自动将 deleted 字段更新为 logic-delete-value 的值。
@Service
public class UserService {
@Autowired
private UserMapper userMapper;
public void testDelete() {
// 执行删除操作
int result = userMapper.deleteById(1L);
System.out.println("删除影响行数:" + result);
}
}
执行后,SQL 实际执行的是:
UPDATE user SET deleted = 1 WHERE id = 1 AND deleted = 0;
⚠️ 注意:MyBatis-Plus 在更新时会加上
AND deleted = 0条件,防止重复删除。
步骤 6:查询时自动过滤已删除数据
所有 select 查询(包括 selectById, selectList 等)都会自动加上 AND deleted = 0 条件。
List<User> users = userMapper.selectList(null);
生成的 SQL:
SELECT id, name, email, deleted FROM user WHERE deleted = 0;
三、常见错误与解决方案
| 错误现象 | 原因 | 解决方案 |
|---|---|---|
| 删除操作仍为物理删除 | 未配置 logic-delete-value 或未加 @TableLogic |
检查配置文件和注解是否正确 |
| 查询结果包含已删除数据 | 全局配置未生效或注解缺失 | 确保 @TableLogic 存在且字段名匹配 |
报错 Unknown column 'deleted' in 'where clause' |
实体字段名与数据库不一致 | 使用 @TableField("is_deleted") 显式指定列名 |
更新操作报错 Data truncation: Incorrect integer value |
logic-delete-value 类型不匹配 |
确保配置值与数据库字段类型兼容(如 TINYINT 用 0/1) |
四、注意事项
字段默认值必须为
logic-not-delete-value
如deleted DEFAULT 0,否则新插入数据可能被视为已删除。不要手动设置
deleted字段值
插入数据时,不要手动赋值deleted = 0,MyBatis-Plus 会自动处理。避免在 WHERE 条件中手动写
deleted = 0
框架已自动处理,重复写可能导致 SQL 错误。批量删除也支持逻辑删除
deleteBatchIds、deleteByMap等方法同样会触发逻辑删除。逻辑删除字段不能用于
@TableField(fill = FieldFill.INSERT)
因为 MP 会自动管理该字段,无需填充。
五、使用技巧
技巧 1:自定义逻辑删除值(非 0/1)
如果你使用字符串标记:
mybatis-plus:
global-config:
db-config:
logic-delete-value: 'Y'
logic-not-delete-value: 'N'
实体类字段改为:
@TableLogic
private String deleted; // "Y" 或 "N"
技巧 2:全局配置 vs 局部覆盖
可以在实体字段上通过 @TableLogic 指定局部值,覆盖全局配置:
@TableLogic(value = "1", delval = "0")
private Integer deleted;
value:未删除值(查询条件)delval:已删除值(删除时设置)
⚠️ 注意:
value和delval是@TableLogic的属性,与全局配置方向相反!
技巧 3:强制物理删除(绕过逻辑删除)
使用 deleteByIdWithFill 或直接写 XML:
// 强制物理删除(不推荐)
int result = userMapper.getBaseMapper().getSqlSession().delete(
"com.example.UserMapper.deleteById", 1L
);
或使用 Wrapper 强制更新:
LambdaUpdateWrapper<User> wrapper = new LambdaUpdateWrapper<>();
wrapper.eq(User::getId, 1L).set(User::getDeleted, null);
userMapper.update(null, wrapper);
六、最佳实践与性能优化
✅ 最佳实践
统一命名规范
所有表使用deleted字段,类型为TINYINT(1),默认0。使用默认值配置
保持logic-delete-value: 1和logic-not-delete-value: 0,减少配置复杂度。索引优化
为deleted字段添加索引,尤其是大表:ALTER TABLE user ADD INDEX idx_deleted (deleted);软删除 + 定期归档
逻辑删除后,定期将deleted = 1的数据归档到历史表,提升主表性能。审计日志结合
配合@TableField(fill = FieldFill.INSERT_UPDATE)记录delete_time。
⚡ 性能优化建议
- 避免在高频查询中使用
SELECT *:deleted字段会参与索引,尽量只查必要字段。 - 复合索引注意顺序:如
(status, deleted, create_time),确保deleted在高频过滤字段之后。 - 定期清理:对长期
deleted = 1的数据进行归档或物理删除(需审批)。
七、总结
| 项目 | 推荐值 |
|---|---|
| 字段名 | deleted |
| 数据类型 | TINYINT(1) |
| 默认值 | 0 |
logic-delete-value |
1 |
logic-not-delete-value |
0 |
| 是否加索引 | ✅ 建议加 |
| 是否可为空 | ❌ 不可为空 |
✅ 掌握逻辑删除配置,是使用 MyBatis-Plus 的基础且关键技能,能有效提升数据安全性与系统可维护性。
📌 快速检查清单:
- 数据库字段存在且默认值正确
- 实体类字段加
@TableLogic -
application.yml配置logic-delete-value和logic-not-delete-value - 查询和删除方法正常工作
- 检查 SQL 日志确认是否自动加
deleted = 0条件