DML操作時,你樂觀麼?聊下MyBatis-Plus樂觀鎖

下崗程序員大飛 2022-01-08 05:14:09 阅读数:510

dml 操作 mybatis-plus mybatis

學習要求

良好的java基礎, 熟悉SpringBoot框架,熟悉Mybatis框架

教學目標

了解並掌握MyBatis-Plus 樂觀鎖實現

視頻教程

MyBatisPlus實戰教程與開發建議

概念

多線程環境下如何保證數據庫操作安全呢?常用的一種解决方案就是對操作數據錶進行加鎖處理。根據實現思路不同分:悲觀鎖與樂觀鎖2種。

悲觀鎖:悲觀的認為多事務操作同一數據是及其不安全的,所以A事務在操作數據時,其他任何事務不允許對該數據進行修改,只能等待A事務操作結束後才可以執行。

樂觀鎖:樂觀的認為A事務在操作數據時,期間不會有其他事務進行幹擾,能順利完成事務操作。

實現

悲觀鎖

悲觀鎖解决方案非常簡單,直接在操作sql中加上for update 語句即可

update 錶  set 列=值 where 條件列=值   for update
select * from 錶 where 條件列=值   for update

使用for update 操作,可以認為是給每次操作都加上錶級別悲觀鎖,在事務沒結束前,其他事務必須等待。

事務1

步驟1:啟動事務

步驟2:使用悲觀鎖方式查詢部門錶(此時鎖錶)

步驟3:提交事務 

事務2

在事務執行到步驟2時,執行下面邏輯,發現事務停滯,等待事務1commit之後才繼續往下執行。

注意:並發環境下都不建議使用悲觀鎖,因為悲觀鎖容易鎖錶,導致事務等待,性能低下。

樂觀鎖

樂觀鎖操作跟悲觀鎖區別在於不對操作的數據錶進行加鎖,而是使用version字段去規避。

以部門錶為例子

步驟1:給部門錶添加version列,默認值為0

步驟2:實現樂觀鎖操作

需求: 修改id=1數據sn字段改為:kfb

1>先查詢

select id, name, sn, version from department where id = 1;

得到該數據列version = 0

2>再修改, 注意version版本更新

update department set sn = "kfb", version = version + 1 where id = 1 and version = 0

這裏有2個注意要點:

1:更新 sn字段的同時,version列數據也跟隨變動

2:更新sql 除了基本的id=1條件外,多了version = 0 條件。

為什麼要這麼設計? 原因:樂觀鎖操作沒有加鎖,任意事務都可以同步操作,多事務同時操作,總有一個先成功,一成功則修改了version字段值,其他事務version 條件自然就不上啦,update失敗。

步驟3:判斷更新是否成功

樂觀鎖判斷是否更新成功,就看執行update語句之後,返回的影響數據行數,如果行數大於0錶示修改成功,如果行數等於0錶示修改失敗,放弃這次修改,一切重來。直到修改成功為止。

MyBatis-Plus版樂觀鎖

MyBatis-Plus 使用@Version注解實現樂觀鎖

還是以部門錶為例

步驟1:在部門錶添加version字段

 步驟2:部門實體對象添加version字段

public class Department {
//省略其他字段
@Version
private int version;
}

步驟3:配置類中配置支持攔截器樂觀鎖

@Bean
public MybatisPlusInterceptor optimisticLockerInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}

 步驟4:正常執行更新方法

@Test
public void testUpdate(){
//先查詢
Department dept = departmentMapper.selectById(1L);
//再替換
dept.setId(1L);
dept.setName("小賣部");
dept.setSn("sell");
//最後更新
departmentMapper.updateById(dept);
}

 執行後SQL

UPDATE department SET name=?, sn=?, version=? WHERE id=? AND version=?

MyBatis-Plus會自動講樂觀鎖邏輯加載到sql中

使用Mybatis-Plus注意:

樂觀鎖支持的數據類型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime 僅支持 updateById(id)update(entity, wrapper) 方法 另外,每次操作前都是先查詢,替換,再更新,否則樂觀鎖無效

版权声明:本文为[下崗程序員大飛]所创,转载请带上原文链接,感谢。 https://gsmany.com/2022/01/202201080514084926.html