@TableLogic

注意:本教程使用的数据库脚本、数据模型和环境信息请参考 “MyBatis Plus环境准备” 章节,点击下载示例源码

在 MyBatis Plus 中,@TableLogic 注解用于实现数据库数据逻辑删除。注意,该注解只对自动注入的 sql 起效:

插入(insert)

不作限制

查找(select)

@TableLogic 注解将会在 select 语句的 where 条件添加条件,过滤掉已删除数据,且使用 wrapper.entity 生成的 where 条件会忽略该字段。例如:

SELECT user_id,name,sex,age,deleted FROM user WHERE user_id=1 AND deleted='0'

更新(update)

@TableLogic 注解将会在 update 语句的 where 条件后追加条件,防止更新到已删除数据,且使用 wrapper.entity 生成的 where条件会忽略该字段。例如:

UPDATE user SET deleted='1' WHERE user_id=1 AND deleted='0'

删除(delete)

@TableLogic 注解会将 delete 语句转变为 update 语句,例如:

update user set deleted=1 where id = 1 and deleted=0

@TableLogic 字段类型支持说明:

  • 支持所有数据类型(推荐使用 Integer、Boolean、LocalDateTime)

  • 如果数据库字段使用 datetime,逻辑未删除值和已删除值支持配置为字符串 null,另一个值支持配置为函数来获取值如now()

附录:

(1)逻辑删除是为了方便数据恢复和保护数据本身价值等等的一种方案,但实际就是删除。

(2)如果你需要频繁查出来看就不应使用逻辑删除,而是以一个状态去表示。

@TableLogic 属性

该注解提供了两个属性,分别如下:

value

用来指定逻辑未删除值,默认为空字符串。

delval

用来指定逻辑删除值,默认为空字符串。

当然,你也可以不在 @TableLogic 注解中指定 value 和 delval 属性的值。使用全局逻辑删除配置信息,配置如下:

# application.yml
mybatis-plus:
  global-config:
    db-config:
      # 全局逻辑删除的实体字段名 (since 3.3.0, 配置后可以忽略 @TableLogic 中的配置)
      logic-delete-field: flag
      # 逻辑已删除值(默认为 1)
      logic-delete-value: 1
      # 逻辑未删除值(默认为 0)
      logic-not-delete-value: 0

示例代码

我们在 user 数据表中添加一个 deleted 字段。如果该字段值为1,表示记录被删除。如果该字段值为0,表示记录未被删除。详细步骤如下:

(1)向 user 数据表添加 deleted 字段,sql 如下:

-- 添加一个 deleted 字段,实现逻辑删除
ALTER TABLE `user`
ADD COLUMN `deleted`  varchar(1) NULL DEFAULT 0 COMMENT '是否删除(1-删除;0-未删除)';

(2)创建 user 表的实体类 AnnotationUser7Bean,代码如下:

package com.hxstrive.mybatis_plus.model;

import com.baomidou.mybatisplus.annotation.*;

@TableName(value = "user")
public class AnnotationUser7Bean {
   @TableId(value = "user_id", type = IdType.AUTO)
   private int userId;
   
   @TableField("name")
   private String name;
   
   @TableField("sex")
   private String sex;
   
   @TableField("age")
   private Integer age;
   
   @TableLogic(value = "0", delval = "1")
   private String deleted;
   
   // 忽略 getter 和 setter 方法
   
   @Override
   public String toString() {
      return "UserBean{" +
            "userId=" + userId +
            ", name='" + name + '\'' +
            ", sex='" + sex + '\'' +
            ", age=" + age +
            ", deleted=" + deleted +
            '}';
   }
}

上面代码中,使用 @TableLogic 注解将 deleted 成员变量指定为逻辑删除字段。如下:

@TableLogic(value = "0", delval = "1")
private String deleted;

(3)客户端代码,先查询用户ID为1的用户是否存在。如果存在,则删除该用户信息。然后,查询用户ID小于10的用户信息,代码如下:

package com.hxstrive.mybatis_plus.simple_mapper.annotation;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hxstrive.mybatis_plus.mapper.AnnotationUser7Mapper;
import com.hxstrive.mybatis_plus.model.AnnotationUser7Bean;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
class AnnotationDemo7 {

    @Autowired
    private AnnotationUser7Mapper userMapper;

    @Test
    void contextLoads() throws Exception {
        // 删除用户ID为1的用户信息
        AnnotationUser7Bean oldUserBean = userMapper.selectById(1);
        if(null != oldUserBean) {
            userMapper.deleteById(oldUserBean.getUserId());
        }

        // 查询用户信息
        QueryWrapper<AnnotationUser7Bean> wrapper = new QueryWrapper<>();
        wrapper.lt("user_id", 10);
        for(AnnotationUser7Bean item : userMapper.selectList(wrapper)) {
            System.out.println(item);
        }
    }

}

执行上面代码,将顺序执行如下 SQL 语句:

a、根据用户ID查询用户信息,sql 如下:

Preparing: SELECT user_id,name,sex,age,deleted FROM user WHERE user_id=? AND deleted='0'
Parameters: 1(Integer)

b、根据用户ID删除用户信息,sql 如下:

Preparing: UPDATE user SET deleted='1' WHERE user_id=? AND deleted='0'
Parameters: 1(Integer)

上面 sql 是一个更新语句,这是因为我们使用了逻辑删除,而不是物理删除。

c、查询用户ID小于10的用户信息,sql 如下:

Preparing: SELECT user_id,name,sex,age,deleted FROM user WHERE deleted='0' AND (user_id < ?)
Parameters: 10(Integer)

细心的读者,会发现上面每条 sql 的 where 语句都添加了 “deleted='0'” 条件。这是因为 “deleted='0'” 条件将过滤所有已删除的数据。


说说我的看法
全部评论(

怎么查询deleted=1的记录呢?

回复:

可以自定义逻辑删除字段,不一定使用 deleted 字段。例如:

@Data
@Accessors(chain = true)
public class Common {
private Long id;
private String name;
// 自定义逻辑删除字段
@TableLogic(delval = "1", value = "0")
private Integer otherField;
}

删除的 SQL 如下:

UPDATE common SET other_field=1 WHERE id=? AND other_field=0


关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号