在开发中,逻辑删除是一种常见的需求。所谓逻辑删除,不是将数据从数据库中真正删除,而是通过标记(通常是某个字段,比如 deletedis_deleted)将数据标记为已删除。在查询数据时,会自动过滤掉标记为删除的数据,从而保证查询结果不包含这些“已删除”的数据。

MyBatis-Plus 提供了对逻辑删除的良好支持,开发者只需要做少量配置,就可以轻松实现逻辑删除功能。

一、MyBatis-Plus 逻辑删除的实现原理

MyBatis-Plus 的逻辑删除通过在表中添加一个标记字段(通常是 deleted 字段),该字段用于表示一条记录是否被逻辑删除。当执行删除操作时,MyBatis-Plus 并不会真正执行 DELETE SQL,而是执行 UPDATE 操作,将记录的逻辑删除标记字段修改为指定的删除状态值。

同样,在查询时,MyBatis-Plus 会自动添加过滤条件,忽略掉那些逻辑删除标记为已删除的数据。

典型流程

  • 插入数据时,逻辑删除字段的默认值为未删除(如 0)。
  • 删除数据时,执行 UPDATE 操作,将逻辑删除字段的值修改为已删除(如 1)。
  • 查询数据时,自动加上 WHERE deleted = 0 的条件,过滤已删除的记录。

二、配置 MyBatis-Plus 的逻辑删除

1. 数据库表结构设计

在数据库表中,添加一个字段来表示逻辑删除状态。通常使用 deleted 字段,值为 0 表示未删除,值为 1 表示已删除。

假设我们有一个 User 表,结构如下:

CREATE TABLE users (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50) NOT NULL,
    email VARCHAR(50),
    deleted TINYINT(1) DEFAULT 0 COMMENT '逻辑删除字段,0未删除,1已删除'
);

在这个表中,deleted 字段用来标记记录是否已被逻辑删除。

2. 实体类配置

在实体类中,我们使用 MyBatis-Plus 提供的 @TableLogic 注解来标记逻辑删除字段。

package com.example.demo.model;

import com.baomidou.mybatisplus.annotation.TableLogic;
import lombok.Data;

@Data
public class User {
    private Long id;
    private String name;
    private String email;

    @TableLogic // 标记为逻辑删除字段
    private Integer deleted;
}

通过 @TableLogic 注解,MyBatis-Plus 会自动识别 deleted 字段为逻辑删除字段。

3. 配置文件

application.yml 中,可以配置 MyBatis-Plus 的全局逻辑删除策略,但通常情况下不需要额外配置,MyBatis-Plus 会自动处理逻辑删除字段。

默认情况下,0 代表未删除,1 代表已删除。如果想自定义逻辑删除的值,可以在 application.yml 中进行配置:

mybatis-plus:
  global-config:
    db-config:
      logic-not-delete-value: 0  # 未删除值
      logic-delete-value: 1      # 已删除值
  • logic-not-delete-value:标识未删除的值,默认是 0
  • logic-delete-value:标识已删除的值,默认是 1
4. 使用逻辑删除

现在,我们已经完成了逻辑删除的配置,下面通过 MyBatis-Plus 的 CRUD 操作演示逻辑删除的使用。

插入数据
package com.example.demo;

import com.example.demo.model.User;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/users")
public class UserController {

    @Autowired
    private UserService userService;

    // 添加新用户
    @PostMapping
    public String addUser(@RequestBody User user) {
        userService.save(user);
        return "用户添加成功";
    }
}

插入操作不会影响 deleted 字段的值,默认插入的数据 deleted 字段为 0

查询数据(过滤已删除记录)

MyBatis-Plus 会自动在查询中过滤掉已删除的记录,执行查询时,自动添加 WHERE deleted = 0 的条件。

// 查询所有未删除的用户
@GetMapping
public List<User> getAllUsers() {
    return userService.list();
}

执行查询操作时,MyBatis-Plus 会生成类似如下的 SQL:

SELECT * FROM users WHERE deleted = 0;
执行逻辑删除

使用 MyBatis-Plus 提供的 removeByIdremove 方法进行删除时,MyBatis-Plus 并不会执行物理删除,而是执行 UPDATE 操作,将 deleted 字段的值设置为 1

// 删除用户(逻辑删除)
@DeleteMapping("/{id}")
public String deleteUser(@PathVariable Long id) {
    userService.removeById(id); // 逻辑删除
    return "用户删除成功";
}

执行逻辑删除时,MyBatis-Plus 会生成如下 SQL:

UPDATE users SET deleted = 1 WHERE id = ?;
恢复被逻辑删除的数据

MyBatis-Plus 不提供直接恢复逻辑删除的 API,但我们可以通过 update 方法手动将 deleted 字段的值改回 0,从而实现恢复已删除记录的功能。

// 恢复被逻辑删除的用户
@PutMapping("/restore/{id}")
public String restoreUser(@PathVariable Long id) {
    User user = new User();
    user.setId(id);
    user.setDeleted(0); // 设置为未删除状态
    userService.updateById(user);
    return "用户恢复成功";
}

三、注意事项

  1. 物理删除与逻辑删除的区别

    • 物理删除是直接从数据库中删除记录,而逻辑删除是通过修改字段标记的方式将记录标记为已删除,但数据仍然保留在数据库中。
    • 如果需要执行物理删除,可以直接使用 MyBatis-Plus 提供的 delete 方法,这将真正删除数据而不是更新 deleted 字段。
  2. 逻辑删除与查询

    • 逻辑删除的记录在正常的查询中是不会被返回的,MyBatis-Plus 会自动在查询中加入 WHERE deleted = 0 的条件。
    • 如果你想查询包含已删除数据的记录,则需要手动编写 SQL 查询,忽略逻辑删除字段的条件。
  3. 逻辑删除的 SQL 优化

    • 对于大数据表,建议为逻辑删除字段 deleted 加索引,以提升查询效率,避免因为全表扫描导致性能下降。
    • 逻辑删除字段应该是简单的数值类型(如 TINYINT),避免使用字符串等复杂类型,这样可以提升查询和更新的性能。
  4. 自动填充逻辑删除字段

    • 在一些复杂场景下,可以结合 MyBatis-Plus 的自动填充功能,在删除或恢复记录时自动更新 deleted 字段,避免手动操作。

四、MyBatis-Plus 逻辑删除的优势

  1. 简化开发:MyBatis-Plus 通过注解和全局配置实现了对逻辑删除的自动支持,开发者无需手动写逻辑删除的 SQL 语句。
  2. 降低风险:逻辑删除避免了物理删除带来的数据丢失风险,数据仍然保留在数据库中,可以根据需要恢复。
  3. 自动过滤已删除数据:MyBatis-Plus 会在查询时自动过滤掉已删除的数据,开发者无需额外判断。

五、总结

MyBatis-Plus 的逻辑删除功能通过简单的配置和注解就能实现。在使用过程中,MyBatis-Plus 会自动将删除操作转换为 UPDATE 操作,并在查询时过滤已删除的数据。通过这种方式,开发者可以很方便地实现逻辑删除的需求,并在需要时恢复数据。

在大多数企业级应用中,逻辑删除是一种非常重要的策略,它能够确保数据的可追溯性和安全性,而 MyBatis-Plus 通过简化配置和操作,极大地方便了开发者的工作。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐