MyBatis-Plus高級(jí)擴(kuò)展詳解
MyBatis-Plus高級(jí)擴(kuò)展
邏輯刪除實(shí)現(xiàn)
概念:
邏輯刪除,可以方便地實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)記錄的邏輯刪除而不是物理刪除。邏輯刪除是指通過(guò)更改記錄的狀態(tài)或添加標(biāo)記字段來(lái)模擬刪除操作,從而保留了刪除前的數(shù)據(jù),便于后續(xù)的數(shù)據(jù)分析和恢復(fù)。
- 物理刪除:真實(shí)刪除,將對(duì)應(yīng)數(shù)據(jù)從數(shù)據(jù)庫(kù)中刪除,之后查詢不到此條被刪除的數(shù)據(jù)
- 邏輯刪除:假刪除,將對(duì)應(yīng)數(shù)據(jù)中代表是否被刪除字段的狀態(tài)修改為“被刪除狀態(tài)”,之后在數(shù)據(jù)庫(kù)中仍舊能看到此條數(shù)據(jù)記錄
邏輯刪除實(shí)現(xiàn):
- 數(shù)據(jù)庫(kù)和實(shí)體類添加邏輯刪除字段
- 表添加邏輯刪除字段可以是一個(gè)布爾類型、整數(shù)類型或枚舉類型。
ALTER TABLE USER ADD deleted INT DEFAULT 0 ; # int 類型 1 邏輯刪除 0 未邏輯刪除
- 實(shí)體類添加邏輯刪除屬性
@Data public class User { // @TableId private Integer id; private String name; private Integer age; private String email; @TableLogic //邏輯刪除字段 int mybatis-plus下,默認(rèn) 邏輯刪除值為1 未邏輯刪除 0 private Integer deleted; }
- 指定邏輯刪除字段和屬性值
單一指定
@Data public class User { // @TableId private Integer id; private String name; private Integer age; private String email; @TableLogic //邏輯刪除字段 int mybatis-plus下,默認(rèn) 邏輯刪除值為1 未邏輯刪除 1 private Integer deleted; }
全局指定
mybatis-plus: global-config: db-config: logic-delete-field: deleted # 全局邏輯刪除的實(shí)體字段名(since 3.3.0,配置后可以忽略不配置步驟2) logic-delete-value: 1 # 邏輯已刪除值(默認(rèn)為 1) logic-not-delete-value: 0 # 邏輯未刪除值(默認(rèn)為 0)
- 演示邏輯刪除操作
邏輯刪除以后,沒(méi)有真正的刪除語(yǔ)句,刪除改為修改語(yǔ)句!刪除代碼:
//邏輯刪除 @Test public void testQuick5(){ //邏輯刪除 userMapper.deleteById(5); }
執(zhí)行效果:
JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@5871a482] will not be managed by Spring ==> Preparing: UPDATE user SET deleted=1 WHERE id=? AND deleted=0 ==> Parameters: 5(Integer) <== Updates: 1
- 測(cè)試查詢數(shù)據(jù)
@Test public void testQuick6(){ //正常查詢.默認(rèn)查詢非邏輯刪除數(shù)據(jù) userMapper.selectList(null); } //SELECT id,name,age,email,deleted FROM user WHERE deleted=0
樂(lè)觀鎖實(shí)現(xiàn)
悲觀鎖和樂(lè)觀鎖場(chǎng)景和介紹
并發(fā)問(wèn)題場(chǎng)景演示:
**解決思路: **
樂(lè)觀鎖和悲觀鎖是在并發(fā)編程中用于處理并發(fā)訪問(wèn)和資源競(jìng)爭(zhēng)的兩種不同的鎖機(jī)制??!
悲觀鎖:
- 悲觀鎖的基本思想是,在整個(gè)數(shù)據(jù)訪問(wèn)過(guò)程中,將共享資源鎖定,以確保其他線程或進(jìn)程不能同時(shí)訪問(wèn)和修改該資源。悲觀鎖的核心思想是"先保護(hù),再修改"。
- 在悲觀鎖的應(yīng)用中,線程在訪問(wèn)共享資源之前會(huì)獲取到鎖,并在整個(gè)操作過(guò)程中保持鎖的狀態(tài),阻塞其他線程的訪問(wèn)。
- 只有當(dāng)前線程完成操作后,才會(huì)釋放鎖,讓其他線程繼續(xù)操作資源。
- 這種鎖機(jī)制可以確保資源獨(dú)占性和數(shù)據(jù)的一致性,但是在高并發(fā)環(huán)境下,悲觀鎖的效率相對(duì)較低。
樂(lè)觀鎖:
- 樂(lè)觀鎖的基本思想是,認(rèn)為并發(fā)沖突的概率較低,因此不需要提前加鎖,而是在數(shù)據(jù)更新階段進(jìn)行沖突檢測(cè)和處理。樂(lè)觀鎖的核心思想是"先修改,后校驗(yàn)"。
- 在樂(lè)觀鎖的應(yīng)用中,線程在讀取共享資源時(shí)不會(huì)加鎖,而是記錄特定的版本信息。
- 當(dāng)線程準(zhǔn)備更新資源時(shí),會(huì)先檢查該資源的版本信息是否與之前讀取的版本信息一致,如果一致則執(zhí)行更新操作,否則說(shuō)明有其他線程修改了該資源,需要進(jìn)行相應(yīng)的沖突處理。
- 樂(lè)觀鎖通過(guò)避免加鎖操作,提高了系統(tǒng)的并發(fā)性能和吞吐量,但是在并發(fā)沖突較為頻繁的情況下,樂(lè)觀鎖會(huì)導(dǎo)致較多的沖突處理和重試操作。
理解點(diǎn):悲觀鎖和樂(lè)觀鎖是兩種解決并發(fā)數(shù)據(jù)問(wèn)題的思路,不是具體技術(shù)!!!
具體技術(shù)和方案:
(1)樂(lè)觀鎖實(shí)現(xiàn)方案和技術(shù):
- 版本號(hào)/時(shí)間戳:為數(shù)據(jù)添加一個(gè)版本號(hào)或時(shí)間戳字段,每次更新數(shù)據(jù)時(shí),比較當(dāng)前版本號(hào)或時(shí)間戳與期望值是否一致,若一致則更新成功,否則表示數(shù)據(jù)已被修改,需要進(jìn)行沖突處理。
- CAS(Compare-and-Swap):使用原子操作比較當(dāng)前值與舊值是否一致,若一致則進(jìn)行更新操作,否則重新嘗試。
- 無(wú)鎖數(shù)據(jù)結(jié)構(gòu):采用無(wú)鎖數(shù)據(jù)結(jié)構(gòu),如無(wú)鎖隊(duì)列、無(wú)鎖哈希表等,通過(guò)使用原子操作實(shí)現(xiàn)并發(fā)安全。
(2)悲觀鎖實(shí)現(xiàn)方案和技術(shù):
- 鎖機(jī)制:使用傳統(tǒng)的鎖機(jī)制,如互斥鎖(Mutex Lock)或讀寫鎖(Read-Write Lock)來(lái)保證對(duì)共享資源的獨(dú)占訪問(wèn)。
- 數(shù)據(jù)庫(kù)鎖:在數(shù)據(jù)庫(kù)層面使用行級(jí)鎖或表級(jí)鎖來(lái)控制并發(fā)訪問(wèn)。
- 信號(hào)量(Semaphore):使用信號(hào)量來(lái)限制對(duì)資源的并發(fā)訪問(wèn)。
介紹版本號(hào)樂(lè)觀鎖技術(shù)的實(shí)現(xiàn)流程:
- 每條數(shù)據(jù)添加一個(gè)版本號(hào)字段version
- 取出記錄時(shí),獲取當(dāng)前 version
- 更新時(shí),檢查獲取版本號(hào)是不是數(shù)據(jù)庫(kù)當(dāng)前最新版本號(hào)
- 如果是[證明沒(méi)有人修改數(shù)據(jù)], 執(zhí)行更新, set 數(shù)據(jù)更新 , version = version+ 1
- 如果 version 不對(duì)[證明有人已經(jīng)修改了],我們現(xiàn)在的其他記錄就是失效數(shù)據(jù)!就更新失敗
使用mybatis-plus數(shù)據(jù)使用樂(lè)觀鎖
- 添加版本號(hào)更新插件
@Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return interceptor; }
- 樂(lè)觀鎖字段添加@Version注解。注意:數(shù)據(jù)庫(kù)也需要添加version字段
ALTER TABLE USER ADD VERSION INT DEFAULT 1 ; # int 類型 樂(lè)觀鎖字段
- 支持的數(shù)據(jù)類型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
- 僅支持 updateById(id) 與 update(entity, wrapper) 方法
@Version private Integer version;
- 正常更新使用即可
//演示樂(lè)觀鎖生效場(chǎng)景 @Test public void testQuick7(){ //步驟1: 先查詢,在更新 獲取version數(shù)據(jù) //同時(shí)查詢兩條,但是version唯一,最后更新的失敗 User user = userMapper.selectById(5); User user1 = userMapper.selectById(5); user.setAge(20); user1.setAge(30); userMapper.updateById(user); //樂(lè)觀鎖生效,失敗! userMapper.updateById(user1); }
防全表更新和刪除實(shí)現(xiàn)
針對(duì) update 和 delete 語(yǔ)句 作用:阻止惡意的全表更新刪除
- 添加防止全表更新和刪除攔截器
@Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new BlockAttackInnerInterceptor()); return interceptor; } }
- 測(cè)試全部更新或者刪除
@Test public void testQuick8(){ User user = new User(); user.setName("custom_name"); user.setEmail("xxx@mail.com"); //Caused by: com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: Prohibition of table update operation //全局更新,報(bào)錯(cuò) userService.saveOrUpdate(user,null); }
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
最新IntelliJ IDEA 2021版配置 Tomcat 8.5 的詳細(xì)步驟
idea開(kāi)發(fā)工具一直是java環(huán)境最好用,很受廣大開(kāi)發(fā)者喜愛(ài),今天通過(guò)本文給大家分享最新IntelliJ IDEA 2021版配置 Tomcat 8.5 的詳細(xì)步驟,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),需要的朋友可以參考下2021-06-06IntelliJ IDEA 2021.1 EAP 1 發(fā)布支持 Java 16 和 WSL 2
這篇文章主要介紹了IntelliJ IDEA 2021.1 EAP 1 發(fā)布支持 Java 16 和 WSL 2,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02Java編程實(shí)現(xiàn)漢字按字母順序排序的方法示例
這篇文章主要介紹了Java編程實(shí)現(xiàn)漢字按字母順序排序的方法,結(jié)合具體實(shí)例形式分析了java編碼轉(zhuǎn)換及字母排序相關(guān)操作技巧,需要的朋友可以參考下2017-07-07SpringBoot+Ajax+redis實(shí)現(xiàn)隱藏重要接口地址的方法
這篇文章主要介紹了SpringBoot+Ajax+redis實(shí)現(xiàn)隱藏重要接口地址,本篇文章主要講訴使用SpringBoot項(xiàng)目配合Ajax和redis實(shí)現(xiàn)隱藏重要接口地址,這里我以隱藏秒殺地址為例,需要的朋友可以參考下2024-03-03mybatisplus添加真正的批量新增、批量更新的實(shí)現(xiàn)
這篇文章主要介紹了mybatisplus添加真正的批量新增、批量更新的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03springboot項(xiàng)目中統(tǒng)一時(shí)間格式處理方法
JacksonConfiguration主要用于配置JSON的序列化和反序列化,而LocalDateTimeFormatter則用于處理請(qǐng)求和響應(yīng)中的LocalDateTime格式,這兩個(gè)配置項(xiàng)在SpringBoot項(xiàng)目中至關(guān)重要,確保數(shù)據(jù)格式的正確處理和傳輸2024-10-10MybatisPlus BaseMapper 中的方法全部 Invalid bound statement (not f
這篇文章主要介紹了MybatisPlus BaseMapper 中的方法全部 Invalid bound statement (not found)的Error處理方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09