Mybatis-Plus逻辑删除时自动填充失效
一、操作顺序
1、逻辑删除全局配置
2、持久化对象设置@TableLogic注解
3、自定义填充逻辑
4、mapper.deleteById(Long)不执行自动填充逻辑
二、源码分析
1、MybatisParameterHandler的processParameter方法如下:
public Object processParameter(Object parameter) {
// 新增或更新
if (parameter != null && (SqlCommandType.INSERT == this.sqlCommanType || SqlCommandType.UPDATE == this.sqlCommandType)) {
// 是否是简单类型参数
if (SimpleTypeRegistry.isSimpleType(parameter.getClass())) {
return parameter;
}
this.exetraParameters(parameter).forEach(this::process);
}
return parameter;
}
2、process方法:
private void process(Object parameter) {
// 省略逻辑
if (tableInfo != null) {
MetaObject metaObject = this.configuration.newMetaObject(entity);
if (SqlCommandType.INSERT == this.sqlCommanType) {
this.populateKeys(tableInfo, metaObject, entity);
// 新增填充
this.insertFill(metaObject, tableInfo);
} else {
// 更新填充
this.updateFill(metaObject, tableInfo);
}
}
}
3、删除api逻辑分析
3.1、delete(QueryWrapper wrapper)
this.exetraParameters(parameter)提取参数为空,不执行填充逻辑
3.2、deleteById(Long)
SimpleTypeRegistry.isSimpleType(parameter.getClass())简单类型参数直接返回,不执行填充逻辑
3.3、deleteById(PO),执行填充逻辑
用法一、new PO().setId(Long),执行填充逻辑时metaObject.getValue("isDeleted")获取不到
用法二、根据id查询出对象作为参数调用deleteById(PO),metaObject.getValue("isDeleted")为0,不执行自动填充
用法三、new PO().setId(Long).setIsDeleted(1)作为参数,调用deleteById(PO),删除时填充删除时间、删除人逻辑正常执行。
但是这样使用还有一个问题,在更新和删除时需要填充的字段都加了填充注解(更新时自动填充更新人、更新时间,删除时自动填充删除人、删除时间),这样删除进入自定义填充逻辑时,参数没有更新人、更新时间信息,会导致更新人、更新时间被置为null
三、正确用法:
1、逻辑删除全局配置
mybatis-plus:
global-config:
db-config:
logic-delete-field: isDeleted # 全局逻辑删除字段名
logic-delete-value: 1 # 逻辑已删除值
logic-not-delete-value: 0 # 逻辑未删除值
2、持久化对象示例
@Data
@TableName(value = "t_order")
public class Order {
@TableId(type = IdType.ASSIGN_ID)
private Long id;
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createdAt;
@TableField(fill = FieldFill.INSERT)
private Long createdBy;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updatedAt;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Long updatedBy;
@TableLogic(value = "0", delval = "1")
private Integer isDeleted;
@TableField(fill = FieldFill.UPDATE)
private LocalDateTime deletedAt;
@TableField(fill = FieldFill.UPDATE)
private Long deletedBy;
}
3、自动填充示例
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
log.info("开始插入填充...");
LocalDateTime localDateTime = LocalDateTime.now();
this.strictInsertFill(metaObject, "createdAt", LocalDateTime.class, localDateTime);
this.strictInsertFill(metaObject, "createdBy", Long.class, getLoginUserId());
this.strictInsertFill(metaObject, "updatedAt", LocalDateTime.class, localDateTime);
this.strictInsertFill(metaObject, "updatedBy", Long.class, getLoginUserId());
}
@Override
public void updateFill(MetaObject metaObject) {
log.info("开始更新填充...");
Object isDeleted = metaObject.getValue("isDeleted");
// 逻辑删除时填充删除时间和删除人
if (isDeleted != null && (Integer) isDeleted == 1) {
this.strictInsertFill(metaObject, "deletedAt", LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(metaObject, "deletedBy", Long.class, getLoginUserId());
} else {
this.strictInsertFill(metaObject, "updatedAt", LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(metaObject, "updatedBy", Long.class, getLoginUserId());
}
}
}
4、逻辑删除时自动填充使用示例
private void deleteOrder(Long id) {
Order order = orderMapper.selectById(id);
order.setIsDeleted(1);
orderMapper.deleteById(order);
}