提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 逻辑删除
-
- 一、配置逻辑删除字段
- 二、逻辑删除流程
- 三、完整代码示例
-
- [1. 实体类定义](#1. 实体类定义)
- [2. Mapper 接口](#2. Mapper 接口)
- [3. SQL语句](#3. SQL语句)
- 四、高级配置
-
- [1. 自定义逻辑删除字段](#1. 自定义逻辑删除字段)
- [2. 排除非逻辑删除字段](#2. 排除非逻辑删除字段)
- 枚举处理
逻辑删除
提示:这里可以添加本文要记录的大概内容:
逻辑删除 是一种数据管理策略,通过标记字段(如 is_deleted
)标识数据状态,而非物理删除数据。
优势:
- 数据可恢复性
- 审计追踪能力
- 避免误删风险
思路:
- 在表中添加一个字段标记数据是否被删除
- 当删除数据时把标记置为 1
- 查询时只查询标记为 0 的数据
一、配置逻辑删除字段
方式一:全局配置(推荐)
就是在application.yaml文件中配置逻辑删除的字段名称和值即可
在 application.yml
中配置全局逻辑删除规则:
yaml
mybatis-plus:
global-config:
db-config:
logic-delete-field: isDeleted # 逻辑删除字段名(实体类字段名)
logic-delete-value: 1 # 删除标记值
logic-not-delete-value: 0 # 未删除标记值
方式二:实体类注解配置
在实体类字段上使用 @TableLogic
注解:
java
@Data
public class User {
@TableLogic
private Integer isDeleted; // 逻辑删除字段(默认值:0未删除,1已删除)
}
优先级:注解配置 > 全局配置。
二、逻辑删除流程
- 删除操作 :自动将
DELETE
语句转换为UPDATE
,设置is_deleted = 1
- 查询操作 :自动附加
WHERE is_deleted = 0
过滤条件
三、完整代码示例
1. 实体类定义
java
@Data
@TableName("tb_user")
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String username;
private Integer balance;
@TableField("is_deleted") // 启用逻辑删除
private Integer isDeleted;
}
2. Mapper 接口
java
public interface UserMapper extends BaseMapper<User> {
// 无需手动编写删除方法
}
3. SQL语句
sql
//删除操作
UPDATE user SET is_deleted = 1 WHERE id = 1 AND is_deleted = 0;
// 查询操作
SELECT * FROM user WHERE is_deleted = 0;
四、高级配置
1. 自定义逻辑删除字段
若数据库字段名或值不符合默认配置,可通过注解指定:
java
@TableLogic(value = "0", delval = "1") // 未删除=0,已删除=1
private Integer status;
2. 排除非逻辑删除字段
若某实体不需要逻辑删除功能:
java
public class Order {
@TableField(exist = false)
private Integer isDeleted; // 忽略逻辑删除字段
}
枚举处理
一、枚举处理场景
将数据库字段与 Java 枚举类型自动映射,常见场景:
- 状态标识:订单状态(0待支付、1已支付、2已取消)
- 类型分类:用户类型(ADMIN 管理员、USER 普通用户)
- 多语言处理:国际化状态码映射
二、核心实现方案
方案 1:使用 @EnumValue
注解(推荐)
实现原理 :
通过注解标记枚举中与数据库字段对应的属性,MyBatis-Plus 自动完成值转换。
步骤 1:定义枚举类
java
public enum UserStatus {
NORMAL(1, "正常"),
FROZEN(2, "冻结");
@EnumValue // 标记数据库存储的值
private final int code;
private final String desc;
UserStatus(int code, String desc) {
this.code = code;
this.desc = desc;
}
}
步骤 2:实体类中使用枚举
java
@Data
@TableName("tb_user")
public class User {
@TableId(type = IdType.AUTO)
private Long id;
private String username;
private UserStatus status; // 直接使用枚举类型
}
步骤 3:全局配置(可选)
在 application.yml
中指定枚举处理策略:
yaml
mybatis-plus:
configuration:
default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
方案 2:实现 IEnum
接口
适用场景:需要更灵活的控制或兼容旧代码。
定义枚举类
java
public enum UserType implements IEnum<Integer> {
ADMIN(1),
USER(2);
private final int code;
UserType(int code) {
this.code = code;
}
@Override
public Integer getValue() { // 定义数据库存储的值
return this.code;
}
}
实体类使用
java
public class User {
private UserType userType; // 自动映射
}
三、高级用法
1. 自定义枚举处理器
场景:需要将枚举转换为 JSON 字符串存储。
步骤 1:实现 TypeHandler
java
@MappedTypes(UserStatus.class)
public class JsonEnumTypeHandler extends BaseTypeHandler<UserStatus> {
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
public void setNonNullParameter(PreparedStatement ps, int i,
UserStatus parameter, JdbcType jdbcType) {
ps.setString(i, objectMapper.writeValueAsString(parameter));
}
// 其他方法实现类似...
}
步骤 2:局部注解配置
java
public class User {
@TableField(typeHandler = JsonEnumTypeHandler.class)
private UserStatus status;
}
2. 多字段枚举映射
场景:需要同时存储枚举编码和描述。
实体类设计
java
public class Order {
private Integer statusCode; // 存储枚举 code
private String statusName;
// 业务方法获取枚举
public OrderStatus getStatus() {
return OrderStatus.of(this.statusCode);
}
}
四、完整示例测试
1. 插入数据
java
@Test
void testInsert() {
User user = new User();
user.setUsername("test");
user.setStatus(UserStatus.FROZEN); // 设置枚举值
userMapper.insert(user);
}
生成 SQL:
sql
INSERT INTO tb_user (username, status) VALUES ('test', 2)
2. 查询数据
java
@Test
void testSelect() {
User user = userMapper.selectById(1L);
System.out.println(user.getStatus()); // 输出: FROZEN
}
生成 SQL:
sql
SELECT id,username,status FROM tb_user WHERE id=1
五、最佳实践
方案 | 适用场景 | 优点 |
---|---|---|
@EnumValue 注解 |
新项目开发 | 配置简洁,代码直观 |
IEnum 接口实现 |
需要兼容旧枚举定义 | 无侵入性改造 |
自定义 TypeHandler | 复杂存储格式(如JSON) | 高度灵活,可定制化 |
统一规范建议:
- 所有业务枚举统一使用
@EnumValue
注解 - 数据库字段名与枚举类名保持语义一致(如
order_status
对应OrderStatus
) - 禁止直接使用
ordinal()
作为存储值(易导致值混乱)
六、常见问题
问题 1:枚举字段查询失效
现象 :使用 QueryWrapper
查询时无法识别枚举值
解决方案:
java
wrapper.eq(User::getStatus, UserStatus.NORMAL); // 直接传入枚举对象
问题 2:数据库存枚举名称
需求 :存储 NORMAL
而非数字编码
配置:
java
public enum UserStatus {
@EnumValue
NORMAL, FROZEN // 默认存储 name()
}
通过合理运用 MyBatis-Plus 的枚举处理机制,可以实现数据库字段与 Java 枚举类型的优雅映射,提升代码可读性和健壮性。