一、核心概念
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
条件