Mybatis Plus 逻辑删除(手把手教学)

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/

截止目前, 星球 内专栏累计输出 66w+ 字,讲解图 2896+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2300+ 小伙伴加入学习 ,欢迎点击围观

前言

大家好,我是小哈。

本小节中,我们将学习如何通过 Mybatis Plus 实现逻辑删除功能。

什么是逻辑删除?

讲逻辑删除之前,先说说物理删除。当我们想要删除数据库中的数据,都会执行一条 delete 语句,执行成功后,会将相关数据彻底从磁盘中删除掉,这种我们称之为物理删除。

逻辑删除其实并不是真正意义上的删除,它其实一条更新语句。

通常做法是在表中新增一个 is_deleted 字段,用来标识该记录的状态,默认值为 0, 表示未删除状态,执行逻辑删除后,会将该字段更新为 1 , 表示已被删除。当然,查询的时候也会带上条件 where is_deleted = 0, 只会查询状态未被删除的记录。

举个栗子,假设小哈跳槽了一个新公司,入职后第一天,都会在公司的 OA 系统中录入员工信息,并分配了一个员工工号,结果小哈干一个星期,发现这个公司代码写的贼烂,坑贼多,考虑再三又离职了,这时候人事会将小哈从 OA 系统的员工库中进行删除,这种情况也是逻辑删除,实际上即时你离职了,还是可以从历史员工库中调出来查看。

为什么需要逻辑删除?

逻辑删除的好处是:

  • 方便恢复数据(比如小哈想明白了,重新回公司入职,更新一个数据状态就行,工号还是那个工号);
  • 数据有挖掘价值(比如电商平台的订单,你虽然手动删除了订单,但是后台并不会删除,还会通过这些订单进行分析,给用户打标签,从而推荐给用户相类似的商品)

TIP : 要不要使用逻辑删除,得结合数据价值来看,如果是没有用的数据,还是物理删除比较好,能够节省磁盘空间。

Mybatis Plus 实现逻辑删除

好了,了解完逻辑删除的相关概念,我们来看看 Mybatis Plus 如何实现逻辑删除。

新建测试表

删除前面小节中用户表,重新创建一张带有逻辑删除字段的用户表,Schema 建表脚本如下:

最佳实践:逻辑删除字段请添加默认值 0,防止后面新增数据时,还需要手动设置。

CREATE TABLE `t_user` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `name` varchar(30) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '姓名',
  `age` int(11) DEFAULT NULL COMMENT '年龄',
  `gender` tinyint(2) NOT NULL DEFAULT 0 COMMENT '性别,0:女 1:男',
  `is_deleted` tinyint(2) NOT NULL DEFAULT 0 COMMENT '逻辑删除(0:未删除,1:已删除)',	
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='用户表';

实体类

model 包下创建 User 实体类:

/**
 * @author: 犬小哈
 * @from: 公众号:小哈学Java, 网站:www.quanxiaoha.com
 * @date: 2022-12-13 14:13
 * @version: v1.0.0
 * @description: TODO
 **/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@TableName("t_user")
public class User {
    /**
     * 主键 ID
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     * 姓名
     */
    private String name;
    /**
     * 年龄
     */
    private Integer age;
    /**
     * 性别
     */
    private Integer gender;

    /**
     * 逻辑删除
     */
    @TableLogic
    private Integer isDeleted;
}

注意,Mybatis Plus 提供了 @TableLogic 逻辑删除注解,只要添加在相关字段上,即可拥有逻辑删除功能。

TIP : @Data @Builder @AllArgsConstructor @NoArgsConstructor 都是 Lombok 注解,偷懒用的,加上它即编译自动添加 getXXX/setXXX类构造器 等相关方法,不了解的小伙伴可自行搜索一下如何使用。

单元测试

完成前面的工作后,我们新建单元测试,看看好不好使:

新增数据

新增一条测试数据,为后面测试做准备:

@Test
void testTableLogic() {
    // 添加测试数据
    User user = User.builder()
                    .name("犬小哈")
                    .age(30)
                    .gender(1)
                    .build();
    userMapper.insert(user);
}

修改数据

修改记录,看看实际执行的 SQL 是什么:

    @Test
    void testTableLogic() {
        // 根据 ID 修改记录
        User user = User.builder().id(1L).name("www.quanxiaoha.com").build();
        userMapper.updateById(user);
    }

执行单元测试,实际执行 SQL 如下,可以看到自动附带上了逻辑删除字段的条件 is_deleted = 0

再来看看根据 Wrapper 条件构造器来修改记录:

    @Test
    void testTableLogic() {
        User user1 = User.builder().name("www.quanxiaoha.com").build();
        // 修改 name 等于 犬小哈 的记录
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.eq("name", "犬小哈");
        userMapper.update(user1, wrapper);

    }

执行单元测试,实际执行 SQL 如下, 同样也是 OK 的:

删除记录

最后看看,删除记录是不是执行了更新操作,将 is_deleted 字段更新为了 1 , 单元测试代码如下:

    @Test
    void testTableLogic() {
		// 删除 ID 为 1 的记录
        userMapper.deleteById(1L);
    }

控制台打印 SQL 如下, 效果完美:

结语

本小节中,我们了解了什么是逻辑删除,以及使用逻辑删除的好处,最后演示了 Mybatis Plus 如何实现逻辑删除,还是非常方便的,简简单单一个注解就搞定了。