MyBatis-Flex 邏輯刪除的用法小結(jié)
一、@Column
MyBatis-Flex 提供了 @Column 用來對(duì)字段進(jìn)行更多的配置,以下是 @Column 的代碼定義:
public @interface Column { /** * 字段名稱 */ String value() default ""; /** * 是否忽略該字段,可能只是業(yè)務(wù)字段,而非數(shù)據(jù)庫對(duì)應(yīng)字段 */ boolean ignore() default false; /** * insert 的時(shí)候默認(rèn)值,這個(gè)值會(huì)直接被拼接到 sql 而不通過參數(shù)設(shè)置 */ String onInsertValue() default ""; /** * update 的時(shí)候自動(dòng)賦值,這個(gè)值會(huì)直接被拼接到 sql 而不通過參數(shù)設(shè)置 */ String onUpdateValue() default ""; /** * 是否是大字段,大字段 APT 不會(huì)生成到 DEFAULT_COLUMNS 里 */ boolean isLarge() default false; /** * 是否是邏輯刪除字段,一張表中只能存在 1 一個(gè)邏輯刪除字段 * 邏輯刪除的字段,被刪除時(shí),會(huì)設(shè)置為 1,正常狀態(tài)為 0 */ boolean isLogicDelete() default false; /** * 是否為樂觀鎖字段,若是樂觀鎖字段的話,數(shù)據(jù)更新的時(shí)候會(huì)去檢測(cè)當(dāng)前版本號(hào),若更新成功的話會(huì)設(shè)置當(dāng)前版本號(hào) +1 * 只能用于數(shù)值的字段 */ boolean version() default false; /** * 配置的 jdbcType */ JdbcType jdbcType() default JdbcType.UNDEFINED; /** * 自定義 TypeHandler */ Class<? extends TypeHandler> typeHandler() default UnknownTypeHandler.class; }
二、邏輯刪除相關(guān)場景
通過@Column設(shè)置字段邏輯刪除
邏輯刪除指的是在刪除數(shù)據(jù)的時(shí)候,并非真正的去刪除,而是將表中列所對(duì)應(yīng)的狀態(tài)字段(status)做修改操作, 實(shí)際上并未刪除目標(biāo)數(shù)據(jù)。
我們可以進(jìn)行表的字段設(shè)計(jì)時(shí),用一個(gè)列標(biāo)識(shí)該數(shù)據(jù)的 "刪除狀態(tài)",在 mybatis-flex 中,正常狀態(tài)的值為 0, 已刪除 的值為 1(可以通過設(shè)置 FlexGlobalConfig 來修改這個(gè)值)。
@Column(isLogicDelete = true) private int isDeleted; /* 對(duì)應(yīng)數(shù)據(jù)庫的表結(jié)構(gòu)中為: is_deleted tinyint(1) default 0 numm comment '是否已邏輯刪除 0-否 1-是'; */
當(dāng) "tb_account" 的數(shù)據(jù)被刪除時(shí)( is_delete = 1 時(shí)),我們通過 MyBatis-Flex 的 selectOneById 去查找數(shù)據(jù)時(shí),會(huì)查詢不到數(shù)據(jù)。 原因是 selectOneById
會(huì)自動(dòng)添加上 is_delete = 0
條件,執(zhí)行的 sql 如下:
SELECT * FROM tb_account where id = ? and is_delete = 0
不僅僅是 selectOneById 方法會(huì)添加 is_delete = 0
條件,BaseMapper 的以下方法也都會(huì)添加該條件:
- selectOneBy**
- selectListBy**
- selectCountBy**
- paginate
同時(shí),比如 Left Join 或者子查詢等,若 子表也設(shè)置了邏輯刪除字段, 那么子表也會(huì)添加相應(yīng)的邏輯刪除條件,例如:
QueryWrapper query1 = QueryWrapper.create() .select() .from(ACCOUNT) .leftJoin(ARTICLE).as("a").on(ACCOUNT.ID.eq(ARTICLE.ACCOUNT_ID)) .where(ACCOUNT.AGE.ge(10)); /* 其執(zhí)行的 SQL 如下: SELECT * FROM `tb_account` LEFT JOIN `tb_article` AS `a` ON `a`.`is_delete` = 0 and `tb_account`.`id` = `a`.`account_id` WHERE `tb_account`.`age` >= 10 AND `tb_account`.`is_delete` = 0 */
在 left join on 條件自動(dòng)添加a.is_delete = 0,并在 where 條件添加上 tb_account.is_delete = 0。
在邏輯刪除的基礎(chǔ)上,自動(dòng)更新更新時(shí)間update_time
(1)數(shù)據(jù)填充指的是,當(dāng) Entity 數(shù)據(jù)被插入或者更新的時(shí)候,會(huì)為字段進(jìn)行一些默認(rèn)的數(shù)據(jù)設(shè)置。這個(gè)非常有用,比如當(dāng)某個(gè) entity 被插入時(shí)候 會(huì)設(shè)置一些數(shù)據(jù)插入的時(shí)間、數(shù)據(jù)插入的用戶 id,多租戶的場景下設(shè)置當(dāng)前租戶信息等等。
MyBatis-Flex 提供了兩種方式,幫助開發(fā)者進(jìn)行數(shù)據(jù)填充。
- 通過 @Table 注解的 onInsert 和 onUpdate配置進(jìn)行操作。
- 通過 @Column 注解的 onInsertValue 和 onUpdateValue配置進(jìn)行操作。
@Table的注解和@Column注解的填充有什么區(qū)別?
- @Table 注解的 onInsert 主要是在 Java 應(yīng)用層面進(jìn)行數(shù)據(jù)設(shè)置。
- @Column 注解的 onInsertValue 則是在數(shù)據(jù)庫層面進(jìn)行數(shù)據(jù)設(shè)置。
首先,需要在后端項(xiàng)目的model實(shí)體類中,通過注解配置將該類的對(duì)象屬性createTime和updateTime,映射到數(shù)據(jù)庫表中的特定字段create_time和update_time的默認(rèn)值設(shè)置等信息。
@Column(onInsertValue = "now()") private Date createTime; @Column(onUpdateValue = "now()", onInsertValue = "now()") private Date updateTime; @Column(isLogicDelete = true) private int isDeleted; /* 對(duì)應(yīng)數(shù)據(jù)庫的表結(jié)構(gòu)中為: create_time timestamp null comment '創(chuàng)建時(shí)間'; update_time timestamp null comment '更新時(shí)間'; is_deleted tinyint(1) default 0 numm comment '是否已邏輯刪除 0-否 1-是'; */
其中,onInsertValue表示當(dāng)數(shù)據(jù)被更新時(shí),設(shè)置的默認(rèn)值。onInsertValue配置的內(nèi)容 "now()" 會(huì)直接參與 SQL 的賦值拼接。而onUpdateValue表示當(dāng)數(shù)據(jù)被更新時(shí),設(shè)置的默認(rèn)值。onUpdateValue配置的內(nèi)容 "now()" 會(huì)直接參與 SQL 的賦值拼接。
在 insert 中,onInsertValue 配置的內(nèi)容會(huì)直接參與 SQL 拼接,而不是通過 JDBC 的 Statement 參數(shù)設(shè)置,需要開發(fā)者注意 onInsertValue 的內(nèi)容,否則可能會(huì)造成 SQL 錯(cuò)誤。
(2)UpdateChain 是一個(gè)對(duì) UpdateEntity、UpdateWrapper 等進(jìn)行封裝的一個(gè)工具類,方便用戶用于進(jìn)行鏈?zhǔn)讲僮鳌?/p>
假設(shè)我們要更新 Account 的 userName 為 "張三",更新年齡在之前的基礎(chǔ)上加 1,更新代碼如下:
@Test public void testUpdateChain() { UpdateChain.of(Account.class) .set(Account::getUserName, "張三") .setRaw(Account::getAge, "age + 1") .where(Account::getId).eq(1) .update(); } /* 以上方法調(diào)用時(shí),MyBatis-Flex 內(nèi)部執(zhí)行的 SQL 如下: sql UPDATE `tb_account` SET `user_name` = '張三' , `age` = age + 1 WHERE `id` = 1 */
經(jīng)過測(cè)試之后,發(fā)現(xiàn)dataMapper.deleteBatchById(idsList)似乎不會(huì)自動(dòng)更新時(shí)間update_time,不知道為什么。不是說當(dāng)調(diào)用 deleteBatchById()方法時(shí),MyBatis-Flex 會(huì)根據(jù)實(shí)體類信息和注解配置,動(dòng)態(tài)生成一條更新語句,而不是刪除語句嗎??按道理來說,更新語句不應(yīng)該會(huì)觸發(fā)更新時(shí)間update_time字段的自動(dòng)更新嗎?(沒搞明白。。)
因此,可以通過MyBatis-Flex 提供的鏈?zhǔn)讲僮鞣绞?,來替換掉基礎(chǔ)的deletedById()方法。
// dataMapper.deleteBatchByIds(idsList); UpdateChain.of(dataMapper) .set(DataModel::getIsDeleted, 1) .where(DataModel::getIsDeleted, 0) .and(DataModel::getId).in(idsList) .update();
這樣MyBatis-Flex框架就會(huì)走更新語句的流程,數(shù)據(jù)庫表中就可以完成自動(dòng)更新update_time更新時(shí)間字段了。
跳過邏輯刪除處理
在某些場景下,比如說需要構(gòu)建回收站功能,那我們?cè)趫?zhí)行查詢、更新或刪除數(shù)據(jù)時(shí),有必要跳過 MyBatis-Flex 自動(dòng)添加的邏輯刪除的相關(guān)條件。
此時(shí),我們可以使用 LogicDeleteManager.execWithoutLogicDelete() 方法處理。這種方法在需要對(duì)所有數(shù)據(jù)進(jìn)行操作時(shí)非常有用,比如批量導(dǎo)出數(shù)據(jù)、進(jìn)行數(shù)據(jù)恢復(fù)等場景。
LogicDeleteManager 是一個(gè)用于處理邏輯刪除的管理器。execWithoutLogicDelete() 方法的作用是在執(zhí)行某些操作時(shí)忽略邏輯刪除的規(guī)則。這意味著,當(dāng)使用這個(gè)方法執(zhí)行查詢、插入、更新或刪除操作時(shí),系統(tǒng)不會(huì)考慮邏輯刪除標(biāo)志,即會(huì)處理所有數(shù)據(jù),包括那些被標(biāo)記為已刪除的數(shù)據(jù)。
比如,
LogicDeleteManager.execWithoutLogicDelete(()-> accountMapper.deleteById(1) );
以上代碼中,accountMapper 會(huì)直接對(duì) Account 數(shù)據(jù)進(jìn)行物理刪除,忽略邏輯刪除字段配置。
代碼如下:
LogicDeleteManager.execWithoutLogicDelete(()->{ // 此處寫邏輯 UpdateChain.of(dataMapper) .set(DataModel::getIsDeleted, 0) .where(DataModel::getIsDeleted, 1) .and(DataModel::getId).in(idsList) .update(); });
上述代碼中,UpdateChain.of(dataMapper) 創(chuàng)建了一個(gè)數(shù)據(jù)映射器對(duì)象dataMapper的更新鏈對(duì)象。.set(DataModel::getIsDeleted, 0) 設(shè)置 DataModel 的 isDeleted 字段值為 0,表示未刪除狀態(tài)。.where(DataModel::getIsDeleted, 1) 指定更新條件之一是isDeleted 字段值為 1,即邏輯上已被刪除的數(shù)據(jù)。.and(DataModel::getId).in(idsList) 添加額外的條件:id 字段的值必須在 idsList 列表中。.update() 執(zhí)行更新操作。
這段代碼的目的是在邏輯刪除被忽略的情況下,將指定 id 的數(shù)據(jù)從邏輯刪除狀態(tài)恢復(fù)到未刪除狀態(tài)。具體來說,只有那些 isDeleted 字段值為 1 并且 id 在 idsList 中的數(shù)據(jù)才會(huì)被更新。更新后,這些數(shù)據(jù)的 isDeleted 字段值會(huì)被設(shè)置為 0,表示這些數(shù)據(jù)不再被視為已刪除。
到此這篇關(guān)于MyBatis-Flex 邏輯刪除的用法小結(jié)的文章就介紹到這了,更多相關(guān)MyBatis-Flex 邏輯刪除內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- MyBatis-Flex實(shí)現(xiàn)分頁查詢的示例代碼
- Mybatis-flex整合達(dá)夢(mèng)數(shù)據(jù)庫的實(shí)現(xiàn)示例
- Spring Boot整合MyBatis-Flex全過程
- SpringBoot使用MyBatis-Flex實(shí)現(xiàn)靈活的數(shù)據(jù)庫訪問
- mybatis-flex實(shí)現(xiàn)鏈?zhǔn)讲僮鞯氖纠a
- mybatis-flex實(shí)現(xiàn)多數(shù)據(jù)源操作
- MyBatis-Flex實(shí)現(xiàn)多表聯(lián)查(自動(dòng)映射)
- Springboot集成Mybatis-Flex的示例詳解
- mybatis-flex與springBoot整合的實(shí)現(xiàn)示例
相關(guān)文章
Java 調(diào)用Restful API接口的幾種方式(HTTPS)
這篇文章主要介紹了Java 調(diào)用Restful API接口的幾種方式(HTTPS),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-02-02Spring探秘之如何妙用BeanPostProcessor
BeanPostProcessor也稱為Bean后置處理器,它是Spring中定義的接口,在Spring容器的創(chuàng)建過程中會(huì)回調(diào)BeanPostProcessor中定義的兩個(gè)方法,這篇文章主要給大家介紹了關(guān)于Spring探秘之如何妙用BeanPostProcessor的相關(guān)資料,需要的朋友可以參考下2022-01-01在SpringBoot中使用JWT的實(shí)現(xiàn)方法
這篇文章主要介紹了在SpringBoot中使用JWT的實(shí)現(xiàn)方法,詳細(xì)的介紹了什么是JWT和JWT實(shí)戰(zhàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-12-12Spring?Cloud微服務(wù)架構(gòu)Sentinel數(shù)據(jù)雙向同步
這篇文章主要為大家介紹了Spring?Cloud微服務(wù)架構(gòu)Sentinel數(shù)據(jù)雙向同步示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-10-10Mybatis 查詢語句條件為枚舉類型時(shí)報(bào)錯(cuò)的解決
這篇文章主要介紹了Mybatis 查詢語句條件為枚舉類型時(shí)報(bào)錯(cuò)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01Java Netty實(shí)現(xiàn)心跳機(jī)制過程解析
這篇文章主要介紹了Java Netty實(shí)現(xiàn)心跳機(jī)制過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03MyBatis實(shí)現(xiàn)字段加解密的實(shí)踐
為了數(shù)據(jù)安全問題,有時(shí)候需要將部分敏感字段加密后再入庫,本文主要介紹了MyBatis實(shí)現(xiàn)字段加解密的實(shí)踐,具有一定的參考價(jià)值,感興趣的可以了解一下2023-11-11