請不要自己寫!Spring Boot 一個注解搞定邏輯刪除,支持JPA/MyBatis
環(huán)境:SpringBoot3.4.0
1. 簡介
在軟件開發(fā)中,邏輯刪除作為一種靈活的數(shù)據(jù)處理方式,被廣泛應(yīng)用于各種系統(tǒng)中。特別是在需要保留數(shù)據(jù)歷史或防止誤刪除的場景下,邏輯刪除顯得尤為重要。
通常邏輯刪除之所以被采用,主要有以下幾個原因:
- 數(shù)據(jù)恢復(fù)方便,只需更新數(shù)據(jù)狀態(tài)即可
- 保護數(shù)據(jù)完整性,避免因物理刪除而破壞數(shù)據(jù)關(guān)聯(lián)
- 滿足審計和合規(guī)性要求,保留記錄的存在
- 降低誤操作風(fēng)險,為開發(fā)者提供安全網(wǎng)
然而,邏輯刪除也可能導(dǎo)致數(shù)據(jù)膨脹和查詢復(fù)雜性增加等問題,因此在使用時需要權(quán)衡利弊。
本篇文章將要介紹如何使用JPA和MyBatis來實現(xiàn)邏輯刪除的功能。
2. 實戰(zhàn)案例
2.1 JPA邏輯刪除
基于JPA的邏輯刪除,這里介紹2中實現(xiàn)方案。
使用@SQLDelete注解
在實體類上通過該注解定義執(zhí)行的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) ;
}
最終執(zhí)行SQL
最終執(zhí)行了通過@SQLDelete配置的update語句。
使用@SoftDelete注解
@SoftDelete(
strategy = SoftDeleteType.DELETED,
columnName = "deleted",
converter = DeletedAttributeConverter.class
)
public class Person {
// 這里不需要定義deleted字段
}
默認情況下,@SoftDelete注解使用true和false表示刪除與未刪除。通過converter進行數(shù)據(jù)類型的轉(zhuǎn)換,這里我們將默認使用的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 ;
}
}
當執(zhí)行刪除操作時,輸出如下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>
注意你當前的環(huán)境,不同的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一樣,執(zhí)行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輸出如下:
執(zhí)行update語句更新deleted字段值。
指定標記刪除字段
以上刪除更新字段是根據(jù)全局配置文件中配置的字段名進行更新, 如果個別表是其它字段名時可以通過如下配置:
public class Person {
@TableLogic
private Integer state ;
}
當執(zhí)行刪除時,則會去更新state字段的值,如下SQL輸出:
圖片