最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MyBatisPlus樂(lè)觀鎖和悲觀鎖的實(shí)現(xiàn)示例

 更新時(shí)間:2025年11月30日 15:01:08   作者:222you  
本文主要介紹了MyBatisPlus樂(lè)觀鎖和悲觀鎖,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

1.場(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)多。

2.樂(lè)觀鎖和悲觀鎖

上面的故事,如果是樂(lè)觀鎖,小王保存價(jià)格前,會(huì)檢查下價(jià)格是否被人修改過(guò)了。如果被修改過(guò) 了,則重新取出的被修改后的價(jià)格,  150元,這樣他會(huì)將120元存入數(shù)據(jù)庫(kù)。

如果是悲觀鎖,小李取出數(shù)據(jù)后,小王只能等小李操作完之后,才能對(duì)價(jià)格進(jìn)行操作,也會(huì)保證 最終的價(jià)格是120元。

3.樂(lè)觀鎖實(shí)現(xiàn)

添加插件:

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 添加分頁(yè)插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));

        // 添加樂(lè)觀鎖插件
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return interceptor;
    }

創(chuàng)建表:

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.qcby.entity;

import com.baomidou.mybatisplus.annotation.Version;
import lombok.Data;

@Data
public class Product {
    private Long id;
    private String name;
    private Integer price;

    @Version
    private Integer version;
}

mapper:

package com.qcby.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.qcby.entity.Product;
import org.springframework.stereotype.Repository;

@Repository
public interface ProductMapper extends BaseMapper<Product> {
}

測(cè)試:

package com.qcby;

import com.qcby.entity.Product;
import com.qcby.mapper.ProductMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class MybatisTestOptimisticLock {

    @Autowired
    private ProductMapper productMapper;

    @Test
    public void testOptimisticLock() {
        // 小李查詢商品信息
        Product productLi = productMapper.selectById(1L);
        System.out.println("小李查詢價(jià)格: " + productLi.getPrice() + ", 版本: " + productLi.getVersion());

        // 小王查詢商品信息
        Product productWang = productMapper.selectById(1L);
        System.out.println("小王查詢價(jià)格: " + productWang.getPrice() + ", 版本: " + productWang.getVersion());

        // 小李修改價(jià)格 +50
        productLi.setPrice(productLi.getPrice() + 50);
        int resultLi = productMapper.updateById(productLi);
        System.out.println("小李修改結(jié)果: " + resultLi);

        if (resultLi > 0) {
            Product afterLi = productMapper.selectById(1L);
            System.out.println("小李修改后價(jià)格: " + afterLi.getPrice() + ", 版本: " + afterLi.getVersion());
        }

        // 小王修改價(jià)格 -30
        productWang.setPrice(productWang.getPrice() - 30);
        int resultWang = productMapper.updateById(productWang);
        System.out.println("小王修改結(jié)果: " + resultWang);

        if (resultWang == 0) {
            // 小王修改失敗,需要重新嘗試
            System.out.println("小王修改失敗,版本已變更,需要重新操作");
            Product newProductWang = productMapper.selectById(1L);
            newProductWang.setPrice(newProductWang.getPrice() - 30);
            resultWang = productMapper.updateById(newProductWang);
            System.out.println("小王重試結(jié)果: " + resultWang);
        }

        // 最終價(jià)格
        Product finalProduct = productMapper.selectById(1L);
        System.out.println("最終價(jià)格: " + finalProduct.getPrice() + ", 版本: " + finalProduct.getVersion());
    }
}

實(shí)際流程:

1. 小李查詢: SELECT id,name,price,version FROM t_product WHERE id=1
   結(jié)果: price=100, version=0

2. 小王查詢: SELECT id,name,price,version FROM t_product WHERE id=1
   結(jié)果: price=100, version=0

3. 小李更新: UPDATE t_product SET name=?, price=150, version=1
           WHERE id=1 AND version=0
   成功: version變?yōu)?

4. 小王更新: UPDATE t_product SET name=?, price=70, version=1
           WHERE id=1 AND version=0
   失敗: version條件不匹配

5. 小王重試: 重新查詢 price=150, version=1
           更新: SET price=120, version=2 WHERE id=1 AND version=1
   成功

6. 最終價(jià)格: 120元 (正確的價(jià)格)

4.悲觀鎖

悲觀鎖總是假設(shè)最壞的情況,認(rèn)為共享資源每次被訪問(wèn)的時(shí)候就會(huì)出現(xiàn)問(wèn)題(比如共享數(shù)據(jù)被修改),所以每次在獲取資源操作的時(shí)候都會(huì)上鎖,這樣其他線程想拿到這個(gè)資源就會(huì)阻塞直到鎖被上一個(gè)持有者釋放。也就是說(shuō),共享資源每次只給一個(gè)線程使用,其它線程阻塞,用完后再把資源轉(zhuǎn)讓給其它線程。

到此這篇關(guān)于MyBatisPlus樂(lè)觀鎖和悲觀鎖的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)MyBatisPlus樂(lè)觀鎖和悲觀鎖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • jvm crash的崩潰日志詳細(xì)分析及注意點(diǎn)

    jvm crash的崩潰日志詳細(xì)分析及注意點(diǎn)

    本篇文章主要介紹了jvm crash的崩潰日志詳細(xì)分析及注意點(diǎn)。具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧
    2017-04-04
  • JAVA springboot如何開啟倆端口

    JAVA springboot如何開啟倆端口

    這篇文章主要介紹了JAVA springboot如何開啟倆端口問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • 使用SpringSecurity設(shè)置角色和權(quán)限的注意點(diǎn)

    使用SpringSecurity設(shè)置角色和權(quán)限的注意點(diǎn)

    這篇文章主要介紹了使用SpringSecurity設(shè)置角色和權(quán)限的注意點(diǎn),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • 通過(guò)原理解析Spring mvc的內(nèi)置編碼過(guò)濾器

    通過(guò)原理解析Spring mvc的內(nèi)置編碼過(guò)濾器

    這篇文章通過(guò)原理主要給大家解析了關(guān)于Spring mvc的內(nèi)置編碼過(guò)濾器的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。
    2017-09-09
  • 使用springboot對(duì)外部靜態(tài)資源文件的處理操作

    使用springboot對(duì)外部靜態(tài)資源文件的處理操作

    這篇文章主要介紹了使用springboot對(duì)外部靜態(tài)資源文件的處理操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • 詳解SpringBoot如何實(shí)現(xiàn)統(tǒng)一后端返回格式

    詳解SpringBoot如何實(shí)現(xiàn)統(tǒng)一后端返回格式

    在前后端分離的項(xiàng)目中后端返回的格式一定要友好,不然會(huì)對(duì)前端的開發(fā)人員帶來(lái)很多的工作量。那么SpringBoot如何做到統(tǒng)一的后端返回格式呢?本文將為大家詳細(xì)講講
    2022-04-04
  • Java高級(jí)之HashMap中的entrySet()方法使用

    Java高級(jí)之HashMap中的entrySet()方法使用

    這篇文章主要介紹了Java高級(jí)之HashMap中的entrySet()方法使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • 解決Java?properties文件里面如何寫"\"的問(wèn)題

    解決Java?properties文件里面如何寫"\"的問(wèn)題

    由于properties使用“\”相當(dāng)于是java的轉(zhuǎn)義符,如果想要寫出\的效果,只需修改相應(yīng)的寫法即可,對(duì)java?properties文件里的"\"寫法感興趣的朋友一起看看吧
    2022-04-04
  • 詳解SpringMVC的類型轉(zhuǎn)換及驗(yàn)證方法

    詳解SpringMVC的類型轉(zhuǎn)換及驗(yàn)證方法

    在本篇文章里面我們給大家詳細(xì)分析了SpringMVC的類型轉(zhuǎn)換及驗(yàn)證方法的相關(guān)知識(shí),對(duì)此有需要的朋友們學(xué)習(xí)下吧。
    2018-10-10
  • Java版坦克大戰(zhàn)游戲源碼示例

    Java版坦克大戰(zhàn)游戲源碼示例

    本篇文章主要介紹了Java版坦克大戰(zhàn)游戲源碼示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-10-10

最新評(píng)論

南江县| 平顺县| 文化| 泰宁县| 宁阳县| 启东市| 佳木斯市| 汝州市| 买车| 桂阳县| 特克斯县| 新干县| 镇巴县| 闽侯县| 辉南县| 西吉县| 滦平县| 江西省| 桐乡市| 河西区| 渝中区| 勃利县| 合阳县| 望江县| 丹江口市| 大埔区| 闵行区| 湘西| 泽普县| 西宁市| 聂荣县| 吴旗县| 宁陵县| 松滋市| 内乡县| 广南县| 鹿邑县| 蓝田县| 夏津县| 疏勒县| 海林市|