[MyBatisPlus]乐观锁和悲观锁
樂(lè)觀鎖和悲觀鎖
場(chǎng)景
一件商品,成本價(jià)是80元,售價(jià)是100元。老板先是通知小李,說(shuō)你去把商品價(jià)格增加50元。小李正在玩游戲,耽擱了一個(gè)小時(shí)。正好一個(gè)小時(shí)后,老板覺(jué)得商品價(jià)格增加到150元,價(jià)格太高,可能會(huì)影響銷量。又通知小王,你把商品價(jià)格降低30元。
此時(shí),小李和小王同時(shí)操作商品后臺(tái)系統(tǒng)。小李操作的時(shí)候,系統(tǒng)先取出商品價(jià)格100元;小王也在操作,取出的商品價(jià)格也是100元。小李將價(jià)格加了50元,并將100+50=150元存入了數(shù)據(jù)庫(kù);小王將商品減了30元,并將100-30=70元存入了數(shù)據(jù)庫(kù)。是的,如果沒(méi)有鎖,小李的操作就完全被小王的覆蓋了。
現(xiàn)在商品價(jià)格是70元,比成本價(jià)低10元。幾分鐘后,這個(gè)商品很快出售了1千多件商品,老板虧1萬(wàn)多。
上面的故事,如果是樂(lè)觀鎖,小王保存價(jià)格前,會(huì)檢查下價(jià)格是否被人修改過(guò)了。如果被修改過(guò)了,則重新取出的被修改后的價(jià)格,150元,這樣他會(huì)將120元存入數(shù)據(jù)庫(kù)。
如果是悲觀鎖,小李取出數(shù)據(jù)后,小王只能等小李操作完之后,才能對(duì)價(jià)格進(jìn)行操作,也會(huì)保證最終的價(jià)格是120元。
模擬修改沖突
數(shù)據(jù)庫(kù)中增加商品表
CREATE TABLE t_product (id BIGINT(20) NOT NULL COMMENT '主鍵ID', NAME VARCHAR(30) NULL DEFAULT NULL COMMENT '商品名稱', price INT(11) DEFAULT 0 COMMENT '價(jià)格', VERSION INT(11) DEFAULT 0 COMMENT '樂(lè)觀鎖版本號(hào)', PRIMARY KEY (id) );添加數(shù)據(jù)
INSERT INTO t_product (id, NAME, price) VALUES (1, '外星人筆記本', 100);添加實(shí)體
package com.xxxx.mybatisplus.pojo;import lombok.Data;@Data public class Product {private Long id;private String name;private Integer price;private Integer version; }ProductMapper
package com.xxxx.mybatisplus.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.xxxx.mybatisplus.pojo.Product; import org.springframework.stereotype.Repository;@Repository public interface ProductMapper extends BaseMapper<Product> {}測(cè)試
package com.xxxx.mybatisplus;import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.xxxx.mybatisplus.mapper.ProductMapper; import com.xxxx.mybatisplus.mapper.UserMapper; import com.xxxx.mybatisplus.pojo.Product; import com.xxxx.mybatisplus.pojo.User; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest public class MyBatisPlusPluginsTest {@Autowiredprivate UserMapper userMapper;@Autowiredprivate ProductMapper productMapper;@Testpublic void testProduct01(){// 小李查詢商品價(jià)格Product productLi = productMapper.selectById(1);System.out.println("小李查詢的商品價(jià)格 = "+productLi.getPrice());// 100// 小王查詢商品價(jià)格Product productWang = productMapper.selectById(1);System.out.println("小王查詢的商品價(jià)格 = "+productWang.getPrice());// 100// 小李將商品價(jià)格+50productLi.setPrice(productLi.getPrice() + 50);productMapper.updateById(productLi);// 小王將商品價(jià)格-30productWang.setPrice(productWang.getPrice()-30);productMapper.updateById(productWang);// 老板查詢商品價(jià)格Product productBoss = productMapper.selectById(1);System.out.println("老板查詢的商品價(jià)格 = "+productBoss.getPrice());// 70}}樂(lè)觀鎖實(shí)現(xiàn)流程
數(shù)據(jù)庫(kù)中添加version字段
取出記錄時(shí),獲取當(dāng)前version
SELECT id,`name`,price,`version` FROM product WHERE id=1更新時(shí),version + 1,如果where語(yǔ)句中的version版本不對(duì),則更新失敗
UPDATE product SET price=price+50, `version`=`version` + 1 WHERE id=1 AND `version`=1Mybatis-Plus實(shí)現(xiàn)樂(lè)觀鎖
修改實(shí)體類
修改配置類
測(cè)試
優(yōu)化修改流程
@Testpublic void testProduct01(){// 小李查詢商品價(jià)格Product productLi = productMapper.selectById(1);System.out.println("小李查詢的商品價(jià)格 = "+productLi.getPrice());// 100// 小王查詢商品價(jià)格Product productWang = productMapper.selectById(1);System.out.println("小王查詢的商品價(jià)格 = "+productWang.getPrice());// 100// 小李將商品價(jià)格+50productLi.setPrice(productLi.getPrice() + 50);productMapper.updateById(productLi);// 小王將商品價(jià)格-30productWang.setPrice(productWang.getPrice()-30);int result = productMapper.updateById(productWang);if (result == 0){// 操作失敗,重試Product productNew = productMapper.selectById(1);productNew.setPrice(productNew.getPrice() - 30);productMapper.updateById(productNew);}// 老板查詢商品價(jià)格Product productBoss = productMapper.selectById(1);System.out.println("老板查詢的商品價(jià)格 = "+productBoss.getPrice());// 120}總結(jié)
以上是生活随笔為你收集整理的[MyBatisPlus]乐观锁和悲观锁的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 手机QQ扫码快速登录功能以及好友权限设置
- 下一篇: [MyBatisPlus]通用枚举