Mybatis-Plus逻辑删除时自动填充失效

581 阅读2分钟

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);
}