搞Java开发的小伙伴们肯定对MyBatis-Plus不陌生,今天咱就唠唠它里面两个实用的功能:逻辑删除和批量操作。逻辑删除就像是给数据“打个标记”,而不是真的删掉;批量操作能让咱们高效处理一堆数据记录。下面直接上干货,结合代码详细讲讲!

一、MyBatis-Plus逻辑删除是啥?

逻辑删除可不是真把数据从数据库里抹掉,而是给数据加个特殊标记。比如说,在数据库表里面加个 deleted 字段,用0表示数据正常,1就表示已经被“删除”了。当咱们查询数据的时候,系统会自动把那些 deleted 字段为1的数据过滤掉;删除数据的时候,也不是真的把数据删掉,只是把这个标记改成1就行。这样一来,历史数据能保留下来,平时正常查询也不受影响,是不是很方便?

二、配置逻辑删除

MyBatis-Plus的逻辑删除功能用起来很方便,不过得先做些准备工作。

2.1 表结构设计

假设咱们有个 user 表,里面有 idusernameage 这些字段,还得有个 deleted 字段(类型是int),用来表示数据是否被删除。0代表正常,1就代表被删除了。

2.2 实体类配置

在实体类里,得加个 @TableLogic 注解。看下面这段代码:

import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; // 下面这个User类是和数据库中user表对应的实体类 // @Data注解能自动生成getter、setter等方法,方便操作属性 // @TableName指定了对应的数据库表名 @Data @TableName("user") public class User { private Long id; private String username; private Integer age; // @TableLogic注解标记这个字段是逻辑删除字段 @TableLogic private Integer deleted; } 

2.3 全局配置(可选)

要是想统一设置逻辑删除的相关参数,还可以在 application.yml 里进行全局配置:

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

加了这个全局配置之后,实体类里的 @TableLogic 注解就可以不写了,系统会默认按照全局配置来。

2.4 Mapper配置

Mapper还是老样子,继承 BaseMapper 就行:

public interface UserMapper extends BaseMapper<User> { } 

三、实战:逻辑删除操作

配置好之后,就可以来试试逻辑删除的效果了。逻辑删除主要用 deleteById 或者 delete 方法,MyBatis-Plus会自动把这些删除操作转成 UPDATE 操作。

3.1 单个删除

@SpringBootTest class LogicDeleteTest { // 自动注入UserMapper,方便调用里面的方法操作数据库 @Autowired private UserMapper userMapper; // 这个测试方法用来测试根据id进行逻辑删除的功能 @Test void testDeleteById() { userMapper.deleteById(1L); System.out.println("ID=1 的用户被逻辑删除了!"); } } 

执行完这段代码,去数据库里看,这条记录的 deleted 字段就变成1了,但数据其实还在数据库里。MyBatis-Plus实际执行的SQL是这样的:

UPDATE user SET deleted=1 WHERE id=1 AND deleted=0 

3.2 条件删除

@Test void testDeleteByCondition() { userMapper.delete(new QueryWrapper<User>().eq("age", 25)); System.out.println("25岁的都被逻辑删了!"); } 

对应的SQL语句是:

UPDATE user SET deleted=1 WHERE age=25 AND deleted=0 

四、查询时自动过滤

逻辑删除还有个好处,就是查询数据的时候,系统会自动带上 deleted=0(或者你配置的未删除值)这个条件。看下面这个查询代码:

@Test void testSelect() { List<User> users = userMapper.selectList(null); users.forEach(System.out::println); } 

执行的SQL语句是:

SELECT id, username, age, deleted FROM user WHERE deleted=0 

这样一来,被删除的数据就不会出现在查询结果里,咱们就不用手动去加这个过滤条件了,是不是很省心?

五、想查已删除的数据怎么办?

有时候,咱们可能需要查看那些被逻辑删除的数据,这时候就得动点小脑筋了。

一种方法是自定义SQL语句:

@Select("SELECT * FROM user WHERE deleted=1") List<User> selectDeleted(); 

还有一种方法,就是用 Wrapper 来跳过逻辑删除:

@Test void testSelectWithDeleted() { List<User> users = userMapper.selectList(new QueryWrapper<User>().eq("deleted", 1)); users.forEach(System.out::println); } 

六、使用MyBatis-Plus逻辑删除的注意点

用MyBatis-Plus做逻辑删除,有些地方得注意。

首先,逻辑删除只对MyBatis-Plus自带的方法生效。要是自己写SQL语句,比如用 @Select 或者 @Update,就得自己手动处理 deleted 字段,不然很容易出问题。

其次,配置好逻辑删除字段之后,MyBatis-Plus会自动帮咱们处理 INSERTUPDATE 操作,像插入数据的时候,会自动把 deleted 字段设为默认的未删除值(比如0)。

七、MyBatis-Plus实现逻辑删除的优点

7.1 配置简单,开箱即用

MyBatis-Plus提供了 @TableLogic 注解和全局配置项(像 logic-delete-field 这些),就写那么几行代码,逻辑删除功能就能用起来了。不用咱们自己去写那些复杂的SQL的 UPDATE 语句和数据过滤逻辑,开发效率一下子就提高了不少。

7.2 自动过滤已删除数据

调用MyBatis-Plus的内置方法,比如 selectListselectById 这些,它会自动在SQL语句里加上 WHERE deleted=0(或者你配置的未删除值)这个条件。咱们写业务代码的时候,都不用改,查询出来的结果天然就把已删除的数据过滤掉了。

7.3 默认值自动填充

插入数据的时候,MyBatis-Plus会自动给 deleted 字段填上未删除值(一般就是0);更新数据的时候,也能智能处理这个字段,不用咱们手动去维护,省了不少事儿。

7.4 统一性强

通过全局配置,所有的表都能共用一套逻辑删除规则,比如说逻辑删除字段名、删除值这些。团队一起开发的时候,大家的代码风格统一,后期维护起来也轻松很多。

7.5 与物理删除切换方便

要是项目里有张表不想用逻辑删除了,把 @TableLogic 注解去掉,或者调整一下配置,MyBatis-Plus就能切换成物理删除模式,灵活性还是挺强的。

八、MyBatis-Plus实现逻辑删除的缺点

8.1 自定义SQL不受控

前面也提到过,逻辑删除只对MyBatis-Plus的内置方法生效。要是自己手写SQL语句,像用 @Select 或者 @Update 这些注解写的SQL,系统不会自动给加上 deleted 条件,得咱们自己手动处理。这就很容易出现遗漏,一不注意就可能出问题。

8.2 全局配置不够灵活

有些项目里,不同的表可能需要不同的逻辑删除字段或者值。比如说,有的表用 is_deleted 作为逻辑删除字段,有的表用 deleted。这时候,全局配置就不太好用了,只能在每张表的实体类里单独加 @TableLogic 注解来覆盖全局配置,感觉有点繁琐。

8.3 存在性能隐患

MyBatis-Plus只是实现了逻辑删除的标记和数据过滤功能,但是数据长期积累下来,数据库表可能会越来越大,这个问题它可解决不了。还得咱们开发者自己去做定时清理或者归档,MyBatis-Plus本身没提供这方面的解决方案。

8.4 调试难度增加

因为逻辑删除操作实际上是转成了 UPDATE 操作,所以在日志里看到的SQL语句不像物理删除那么直观。排查问题的时候,可能得仔细多看几眼,确认各个字段的状态,增加了调试的复杂性。

8.5 字段依赖强

逻辑删除功能依赖实体类里的 deleted 字段。要是数据库表结构里没加这个字段,或者字段名和实体类里的不一致,MyBatis-Plus的逻辑删除功能就没法正常工作了。所以数据库设计的时候,得严格和实体类里的字段对齐。

MyBatis-Plus的逻辑删除功能有它的优点,也有一些不足。咱们在实际开发中,得根据项目的具体需求和情况来选择合适的方案。希望这篇文章能帮到大家,要是有啥问题,欢迎在评论区留言讨论!