在很多企業級應用中,數據刪除操作通常采用 邏輯刪除 的方式,而不是物理刪除。邏輯刪除指的是通過更新字段(例如 is_deleted
或 status
)來標記數據為刪除狀態,而不是真的從數據庫中刪除記錄。這樣做的好處是保留數據的歷史記錄,方便后續的數據恢復、審計以及統計。
MyBatis-Plus(MP)提供了強大的 邏輯刪除功能,使得開發者可以快速實現這一功能。本文將介紹 MyBatis-Plus 如何實現邏輯刪除,包括自動填充字段、配置與實現步驟、常見應用場景,并展示如何使用 remove
方法進行邏輯刪除,而不是手動通過 update
來修改刪除標記。
1. 邏輯刪除的必要性
1.1 邏輯刪除的定義
邏輯刪除 是指通過修改某個字段(如 is_deleted
)的值,將記錄標記為已刪除,而不是將其從數據庫中刪除。這種方式不僅保留了數據的完整性,還能避免因誤操作導致的數據丟失。
1.2 邏輯刪除的優點
- 數據恢復:可以在數據標記為刪除后,依然保留數據,便于后期的恢復。
- 歷史審計:可以查看被刪除記錄的歷史數據,滿足合規性要求。
- 避免數據丟失:比物理刪除更安全,可以減少誤操作帶來的影響。
1.3 適用場景
- 用戶賬號刪除:用戶刪除賬戶時,使用邏輯刪除標記賬戶為已刪除,便于后續恢復。
- 訂單或產品狀態管理:刪除訂單或產品記錄時,使用邏輯刪除來標記記錄而非物理刪除。
- 內容管理系統(CMS):在 CMS 中刪除文章或評論時,使用邏輯刪除來保留數據。
2. MyBatis-Plus 支持的邏輯刪除方式
MyBatis-Plus 提供了非常方便的方式來實現邏輯刪除,主要依賴于 @TableLogic
注解,標記字段為邏輯刪除字段。MyBatis-Plus 會自動處理該字段的值,并在查詢時自動排除已刪除的記錄。
2.1 使用 @TableLogic
注解進行邏輯刪除
MyBatis-Plus 提供的 @TableLogic
注解可以標識一個字段為邏輯刪除字段。默認情況下,字段值為 0
表示未刪除,值為 1
表示已刪除。
示例:User
實體類配置
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.IdType;public class User {@TableId(value = "id", type = IdType.AUTO)private Long id;private String name;private Integer age;@TableLogic // 邏輯刪除字段private Integer isDeleted;// Getters and Setters
}
在這個示例中:
@TableLogic
:標識isDeleted
字段為邏輯刪除字段。字段值為0
表示未刪除,值為1
表示已刪除。
2.2 配置邏輯刪除字段的值
MyBatis-Plus 默認將 isDeleted
字段值為 0
表示未刪除,1
表示已刪除。開發者可以自定義邏輯刪除的字段值。
自定義邏輯刪除值
@Configuration
public class MybatisPlusConfig {@Beanpublic MybatisPlusPropertiesCustomizer mybatisPlusPropertiesCustomizer() {return properties -> {properties.getGlobalConfig().setLogicDeleteValue("1"); // 設置邏輯刪除的值為 1properties.getGlobalConfig().setLogicNotDeleteValue("0"); // 設置未刪除的值為 0};}
}
在這個配置中,設置了邏輯刪除字段的值為 1
表示已刪除,0
表示未刪除。
3. 使用 remove
方法進行邏輯刪除
3.1 remove
方法與邏輯刪除
MyBatis-Plus 中的 remove
方法用于刪除記錄,默認情況下會執行物理刪除操作。為了啟用 邏輯刪除,需要通過設置 @TableLogic
注解,并在執行刪除操作時,MyBatis-Plus 會自動更新 isDeleted
字段的值,而不是直接刪除記錄。
示例:remove
方法進行邏輯刪除
public void logicDeleteUser(Long userId) {userService.removeById(userId); // 使用 remove 方法進行邏輯刪除
}
在這個例子中,removeById
方法會自動更新 isDeleted
字段,而不是直接從數據庫中刪除記錄。
3.2 removeById
的原理
removeById
方法的實現是基于 @TableLogic
注解的字段,通過更新 isDeleted
字段的值來實現邏輯刪除。MyBatis-Plus 在執行刪除操作時,會自動生成如下 SQL:
UPDATE user SET is_deleted = 1 WHERE id = ?;
該操作將 is_deleted
字段的值更新為 1
,表示該記錄已被刪除,而不是從數據庫中刪除該記錄。
3.3 查詢時排除邏輯刪除的記錄
MyBatis-Plus 默認會在查詢時自動排除邏輯刪除的記錄,即 isDeleted
字段為 1
的記錄不會被返回。
查詢時的自動排除
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "John");
List<User> users = userService.list(queryWrapper); // 自動排除邏輯刪除的記錄
在這個查詢中,MyBatis-Plus 會自動忽略 isDeleted = 1
的記錄,只返回未刪除的記錄。
4. 示例:邏輯刪除字段與查詢
4.1 插入數據時的邏輯刪除
在插入數據時,isDeleted
字段會默認設置為 0
,表示數據未刪除。
User user = new User();
user.setName("John");
user.setAge(30);
userService.save(user); // 插入時,isDeleted 默認為 0
4.2 更新數據時的邏輯刪除
在更新數據時,可以通過 removeById
方法將某條記錄的 isDeleted
字段更新為 1
,表示數據已被邏輯刪除。
User user = userService.getById(1L);
user.setIsDeleted(1); // 設置為已刪除
userService.updateById(user); // 執行更新操作,實際是邏輯刪除
4.3 查詢時排除邏輯刪除的數據
查詢時,MyBatis-Plus 會自動過濾掉邏輯刪除的記錄。你無需顯式地排除已刪除記錄。
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "John");
List<User> users = userService.list(queryWrapper); // 自動排除邏輯刪除的記錄
4.4 查詢已刪除的記錄
如果需要查詢已刪除的記錄,可以通過 QueryWrapper
手動指定查詢條件:
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("is_deleted", 1); // 查詢已刪除的記錄
List<User> deletedUsers = userService.list(queryWrapper);
5. 總結
- 邏輯刪除的必要性:邏輯刪除可以保留數據歷史,避免數據丟失,適用于需要審計、數據恢復的場景。
- MyBatis-Plus 支持的邏輯刪除方式:通過
@TableLogic
注解,MyBatis-Plus 能夠在插入、更新和查詢時自動處理邏輯刪除字段。 - 實現步驟:在實體類中使用
@TableLogic
注解標識邏輯刪除字段,配置自定義刪除值,并實現MetaObjectHandler
來處理字段填充。 - 使用
remove
方法進行邏輯刪除:MyBatis-Plus 的removeById
方法會自動更新isDeleted
字段,實現邏輯刪除,而不是物理刪除數據。
MyBatis-Plus 的邏輯刪除功能簡化了數據的刪除操作,保留了刪除記錄的歷史數據,確保了應用的數據一致性和安全性。通過合理配置和使用 MyBatis-Plus 的邏輯刪除功能,開發者能夠更加高效地管理數據,并滿足業務需求。 🚀