请不要自己写!Spring Boot 一个注解搞定逻辑删除,支持JPA/MyBatis

开发 前端
在软件开发中,逻辑删除作为一种灵活的数据处理方式,被广泛应用于各种系统中。特别是在需要保留数据历史或防止误删除的场景下,逻辑删除显得尤为重要。

环境:SpringBoot3.4.0

1. 简介

在软件开发中,逻辑删除作为一种灵活的数据处理方式,被广泛应用于各种系统中。特别是在需要保留数据历史或防止误删除的场景下,逻辑删除显得尤为重要。

通常逻辑删除之所以被采用,主要有以下几个原因:

  • 数据恢复方便,只需更新数据状态即可
  • 保护数据完整性,避免因物理删除而破坏数据关联
  • 满足审计和合规性要求,保留记录的存在
  • 降低误操作风险,为开发者提供安全网

然而,逻辑删除也可能导致数据膨胀和查询复杂性增加等问题,因此在使用时需要权衡利弊。

本篇文章将要介绍如何使用JPA和MyBatis来实现逻辑删除的功能。

2. 实战案例

2.1 JPA逻辑删除

基于JPA的逻辑删除,这里介绍2中实现方案。

使用@SQLDelete注解

在实体类上通过该注解定义执行的SQL语句,如下示例:

@Entity
@Table(name = "t_person")
@SQLDelete(sql = "update t_person p set p.deleted = 1 where p.id = ?")
public class Person {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long id ;
  private String name ;
  private Integer age ;
  /**0:正常,1:删除*/
  @Column(columnDefinition = "int default 0")
  private Integer deleted = 0;
  // getters, setters
}

Repository接口定义

public interface PersonRepository extends JpaRepository<Person, Long> {
}

单元测试

@Test
public void testDelete() {
  this.personRepository.deleteById(2L) ;
}

最终执行SQL

图片

最终执行了通过@SQLDelete配置的update语句。

使用@SoftDelete注解

@SoftDelete(
  strategy = SoftDeleteType.DELETED, 
  columnName = "deleted", 
  converter = DeletedAttributeConverter.class
)
public class Person {
  // 这里不需要定义deleted字段
}

默认情况下,@SoftDelete注解使用true和false表示删除与未删除。通过converter进行数据类型的转换,这里我们将默认使用的boolean类型改为0,1表示:

public class DeletedAttributeConverter 
  implements AttributeConverter<Boolean, Integer> {
  @Override
  public Integer convertToDatabaseColumn(Boolean attribute) {
    return attribute == null || !attribute ? 0 : 1;
  }
  @Override
  public Boolean convertToEntityAttribute(Integer dbData) {
    return dbData == null || dbData == 0 ? Boolean.FALSE : Boolean.TRUE ;
  }
}

当执行删除操作时,输出如下SQL:

图片图片

2.2 MyBatis逻辑删除

MyBatis的逻辑删除功能并非由它原生支持,而是由mybatis-plus提供的功能。

首先,引入mybatis-plus依赖:

<dependency>
  <groupId>com.baomidou</groupId>
  <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
  <version>3.5.10.1</version>
</dependency>

注意你当前的环境,不同的Spring Boot版本2/3引入的依赖包不一样。

接下来,进行如下的配置:

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

如上定义后,通过MyBatis-Plus的接口进行删除时,将会与jpa一样,执行update语句。

实体定义:

@TableName("t_person")
public class Person {
  /**0:正常,1:删除*/
  private Integer deleted = 0;
}

Mapper接口定义如下:

public interface PersonMapper extends BaseMapper<Person> {
}

注意,你需要继承MyBatis-Plus的BaseMapper接口。

单元测试

@Test
public void testMyBatisDelete() {
  this.personMapper.deleteById(2L) ;
}

SQL输出如下:

图片

执行update语句更新deleted字段值。

指定标记删除字段

以上删除更新字段是根据全局配置文件中配置的字段名进行更新, 如果个别表是其它字段名时可以通过如下配置:

public class Person {
  @TableLogic
  private Integer state ;
}

当执行删除时,则会去更新state字段的值,如下SQL输出:

图片图片


责任编辑:武晓燕 来源: Spring全家桶实战案例源码
相关推荐

2013-09-25 17:31:08

Storwize V5虚拟化存储

2020-06-09 15:13:15

2013-11-28 09:21:19

2011-08-06 23:03:01

京瓷复合一体机

2009-03-19 10:00:06

2020-06-18 09:40:13

智慧城市数据存储基础架构

2023-12-07 12:38:09

架构低成本开发

2013-01-23 09:40:11

云计算云平台信息化

2010-01-27 15:17:50

2021-12-21 06:36:00

虚拟化VMware虚拟化课程

2021-12-21 23:21:16

DDOS防御安全

2021-03-16 16:38:10

亚马逊云科技EFS

2014-03-13 09:46:36

Linux操作系统开源

2010-03-31 16:35:36

信息化

2019-03-27 10:06:00

SAP沈自所人工智能

2011-03-24 14:57:23

SUSE Linux云计算

2009-04-07 16:08:22

LinuxXenSUSE

2025-02-11 09:39:00

2012-10-18 19:25:21

佳能
点赞
收藏

51CTO技术栈公众号