有时候并不需要真正的删除数据,而是想逻辑删除,方便数据恢复。

MyBatis-Plus可以很方便的实现逻辑删除的功能。

Entity类

首先,数据库表添加一个表示逻辑删除的字段delete_flag

CREATE TABLE `tb_user` (
  `id` bigint NOT NULL COMMENT '主键ID',
  `name` varchar(30) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '姓名',
  `age` int DEFAULT NULL COMMENT '年龄',
  `email` varchar(50) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '邮箱',
  `create_time` timestamp NOT NULL COMMENT '创建时间',
  `update_time` timestamp NOT NULL COMMENT '更新时间',
  `delete_flag` tinyint(1) NOT NULL COMMENT '逻辑删除,0 - 未删除;-1 - 已删除',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci

对应的UserEntity实体类:

@Data
@TableName("tb_user")
public class UserEntity {
    private Long id;
    private String name;
    private Integer age;
    private String email;

    @TableField(value = "create_time", fill = FieldFill.INSERT)
    private Date createTime;

    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;

    private Integer deleteFlag;
}

配置

首先,需要在UserEntity实体类中的deleteFlag字段上进行注解配置:

  • @TableLogic(value = "0", delval = "-1")配置逻辑删除字段的值,value的值表示未删除的时候的值,delval的值表示已删除时候的值;
  • @TableField(value = "delete_flag", fill = FieldFill.INSERT)配置deleteFlag字段的自动填充规则。
@Data
@TableName("tb_user")
public class UserEntity {
    private Long id;
    private String name;
    private Integer age;
    private String email;

    @TableField(value = "create_time", fill = FieldFill.INSERT)
    private Date createTime;

    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;

    @TableLogic(value = "0", delval = "-1")
    @TableField(value = "delete_flag", fill = FieldFill.INSERT)
    private Integer deleteFlag;
}

可以配置deleteFlaginsert数据的时候,默认填充0

/**
 * 自动填充字段值得配置
 */
@Component
public class AutoFillFieldValueConfig implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
        this.strictInsertFill(metaObject, "updateTime", Date.class, new Date());
        this.strictInsertFill(metaObject, "deleteFlag", Integer.class, 0);
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
    }
}

测试一下

下面来测试一下。

首先,添加一个新的用户:

    @Test
    public void testLogicDelete() {
        // 插入一个新的用户
        UserEntity newUser = new UserEntity();
        newUser.setId(11L);
        newUser.setName("Kevin");
        newUser.setAge(25);
        newUser.setEmail("kevin@163.com");
        userMapper.insert(newUser);
    }

控制台日志:

==>  Preparing: INSERT INTO tb_user ( id, name, age, email, create_time, update_time, delete_flag ) VALUES ( ?, ?, ?, ?, ?, ?, ? )
==> Parameters: 11(Long), Kevin(String), 25(Integer), kevin@163.com(String), 2021-09-20 21:29:37.232(Timestamp), 2021-09-20 21:29:37.234(Timestamp), 0(Integer)
<==    Updates: 1

数据库数据:

在这里插入图片描述

可以看到,delete_flag默认填充了0

下面,来测试一下逻辑删除(现在调用所有的删除方法,都是逻辑删除):

    @Test
    public void testLogicDelete() {
        // 插入一个新的用户
//        UserEntity newUser = new UserEntity();
//        newUser.setId(11L);
//        newUser.setName("Kevin");
//        newUser.setAge(25);
//        newUser.setEmail("kevin@163.com");
//        userMapper.insert(newUser);

        // 逻辑删除
        userMapper.deleteById(11L);
    }

控制台日志:

==>  Preparing: UPDATE tb_user SET delete_flag=-1 WHERE id=? AND delete_flag=0
==> Parameters: 11(Long)
<==    Updates: 1

可以看到,删除方法并没有执行DELETE语句,而是执行的UPDATE语句,更新了delete_flag字段的值。

数据库数据:

在这里插入图片描述

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐