MybatisPlus 逻辑删除时实现自动填充删除时间

MybatisPlus 逻辑删除时实现自动填充删除时间

在原有代码上新增逻辑删除:
(1)数据库表 新增字段is_deleted,其值为 0 表示未删除,为 1 表示已删除 ;新增删除时间字段 delete_time

ALTER TABLE user ADD `is_deleted` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否删除(0: 未删除, 1: 已删除)';
ALTER TABLE user ADD `delete_time` datetime DEFAULT NULL COMMENT '删除日期';

(2)配置全局逻辑删除属性
application.yml 中配置 MyBatis-Plus 的全局逻辑删除属性:

mybatis-plus:
  global-config:
    db-config:
      logic-delete-field: isDeleted # 全局逻辑删除字段名
      logic-delete-value: 1 # 逻辑已删除值
      logic-not-delete-value: 0 # 逻辑未删除值

(3)在对应实体类添加相应的字段 isDeleteddeleteTimeisDeleted 字段上添加@TableLogic 注解,deleteTime 字段额外添加 fill = FieldFill.UPDATE

@TableLogic
private Integer isDeleted;
@TableField(value = "delete_time", fill = FieldFill.UPDATE) // 标记为自动填充字段
private LocalDateTime deleteTime;

(4)使用 MybatisPlus 的自动填充字段功能

自动填充功能通过实现 com.baomidou.mybatisplus.core.handlers.MetaObjectHandler接口来实现。创建一个类 MyMetaObjectHandler 来实现该接口,并在其中定义插入和更新时的填充逻辑。

import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;

@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
    @Override
    public void insertFill(MetaObject metaObject) {
    }
    @Override
    public void updateFill(MetaObject metaObject) {
        // 当逻辑删除字段被更新为删除状态时,填充 delete_time
        log.info("开始自动填充删除时间");
        Object isDeleted = metaObject.getValue("isDeleted");
        if (isDeleted != null && (Integer) isDeleted == 1) {
            this.setFieldValByName("deleteTime", LocalDateTime.now(), metaObject);
        }
    }
}

由于逻辑删除是将删除操作转换为更新操作,标记记录为已删除,所以需要在 updateFill 方法内实现 deleteTime 的自动填充代码。注意,如果不增加判断条件if (isDeleted != null && (Integer) isDeleted == 1),非删除的更新操作也会填充删除时间字段。

错误做法

如果删除的条件复杂,需要使用 QueryWrapper 配合删除 ,如下删除时并不会自动填充删除时间。官方文档指出,删除接口自动填充功能会失效。

QueryWrapper<UserMo> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("uid", uid);
queryWrapper.eq("type", 80);
UserMapper.delete(queryWrapper);

官方说明

正确做法 一

官方文档指出,可以使用 deleteById方法 ,使用该方法逻辑删除时就可以触发自动填充字段。

int result = userMapper.deleteById(uid);

但是,直接使用deleteById(uid) ,它适合于自动填充通用的更新时间、更新作者等字段,而对于删除时间的填充,只需要在删除阶段时填充。

为了在 updateFill方法中区别出是更新操作还是删除操作,需要借助 isDeleted 字段。同样使用deleteById() 方法,但选择如下入参为实体类的版本。

int deleteById(T entity);

新建实体类 userMo,单独设置 uid 和 isDeleted=1,updateFill 方法的参数 metaObject 会包含isDeleted 的值,isDeleted 具体存在于 metaObjectobjectWrapper中。

UserMo userMo = new UserMo();
userMo.setUid(uid);
userMo.setIsDeleted(1);
int result = UserMapper.deleteById(userMo);

使用 getValue 方法获取 isDeleted 的值,值为 1 表示该操作为删除操作,而不是更新。

Object isDeleted = metaObject.getValue("isDeleted");

注意,deleteById 虽然可以实现填充的效果,但是where筛选只会根据id进行删除,如果某些业务里面需要添加其他删除条件时无法实现了。

参考来源:
【mybatis-plus】mybatis-plus 删除并自动填充_logicdeletebyidwithfill-优快云博客

正确做法二

如果存在多种删除条件,不仅仅只根据 id,删除方法需要替换为update 方法,而不是 delete 方法。下面的代码采用 手动填充 删除时间字段的方式,注意,该方式无需使用 MyMetaObjectHandler 类。如果删除条件条件复杂的话,推荐使用这种方式。

public int delete(Long topicId) {
    UpdateWrapper<VersionMo> wrapper = new UpdateWrapper<>();
    wrapper.eq("topic_id", topicId).set("is_deleted", 1);
    wrapper.setSql("delete_time = NOW()");
    return vMapper.update(wrapper);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值