中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

MybatisPlus中@Version注解如何使用

發布時間:2022-06-17 09:12:01 來源:億速云 閱讀:159 作者:zzz 欄目:開發技術

這篇文章主要講解了“MybatisPlus中@Version注解如何使用”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“MybatisPlus中@Version注解如何使用”吧!

    注解說明

    在 MyBatis Plus 中,使用 @Version 實現樂觀鎖,該注解用于字段上面

    什么是樂觀鎖

    1 樂觀鎖簡介

    • 樂觀鎖(Optimistic Locking)是相對悲觀鎖而言的,樂觀鎖假設數據一般情況下不會造成沖突

    • 所以在數據進行提交更新的時候,才會正式對數據的沖突進行檢測

    • 如果發現沖突了,則返回給用戶錯誤的信息,讓用戶決定如何去做

    • 樂觀鎖適用于讀操作多的場景,這樣可以提高程序的吞吐量

    2 樂觀鎖實例

    存在兩個線程 A 和 B,分別從數據庫讀取數據。執行后,線程 A 和 線程 B 的 version 均等于 1。如下圖

    MybatisPlus中@Version注解如何使用

    線程 A 處理完業務,提交數據。此時,數據庫中該記錄的 version 為 2。如下圖:

    MybatisPlus中@Version注解如何使用

    線程 B 也處理完業務了,提交數據。此時,數據庫中的 version 已經等于 2,而線程的 version 還是 1。程序給出錯誤信息,不允許線程 B 操作數據。如下圖:

    MybatisPlus中@Version注解如何使用

    • 樂觀鎖機制采取了更加寬松的加鎖機制

    • 樂觀鎖是相對悲觀鎖而言,也是為了避免數據庫幻讀、業務處理時間過長等原因引起數據處理錯誤的一種機制

    • 但樂觀鎖不會刻意使用數據庫本身的鎖機制,而是依據數據本身來保證數據的正確性

    實例代碼

    本實例將在前面用到的 user 表上面進行。在進行之前,現在 user 表中添加 version 字段

    ALTER TABLE `user`
    ADD COLUMN `version`  int UNSIGNED NULL COMMENT '版本信息';

    :::info

    定義 user 表的 JavaBean,代碼如下:

    import com.baomidou.mybatisplus.annotation.*;
     
    @TableName(value = "user")
    public class AnnotationUser5Bean {
       @TableId(value = "user_id", type = IdType.AUTO)
       private String userId;
        
       @TableField("name")
       private String name;
        
       @TableField("sex")
       private String sex;
        
       @TableField("age")
       private Integer age;
        
       @Version
       private int version;
       // 忽略 getter 和 setter 方法
    }

    添加 MyBatis Plus 的樂觀鎖插件,該插件會自動幫我們將 version 加一操作

    注意,這里和分頁操作一樣,需要進行配置,如果不配置,@Version是不會生效的

    import com.baomidou.mybatisplus.annotation.DbType;
    import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
    import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
     
    @Configuration
    public class MybatisPlusConfig {
     
        @Bean
        public MybatisPlusInterceptor paginationInterceptor() {
            MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
            // 樂觀鎖插件
            interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
            return interceptor;
        }
     
    }

    測試樂觀鎖代碼,我們創建兩個線程 A 和 B 分別去修改用戶ID為 1 的用戶年齡,然后觀察年齡和version字段的值

    package com.hxstrive.mybatis_plus.simple_mapper.annotation;
     
    import com.hxstrive.mybatis_plus.mapper.AnnotationUser5Mapper;
    import com.hxstrive.mybatis_plus.model.AnnotationUser5Bean;
    import org.junit.jupiter.api.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.test.context.junit4.SpringRunner;
    import java.util.concurrent.CountDownLatch;
     
    @RunWith(SpringRunner.class)
    @SpringBootTest
    class AnnotationDemo5 {
     
        @Autowired
        private AnnotationUser5Mapper userMapper;
     
        @Test
        void contextLoads() throws Exception {
            // 重置數據
            AnnotationUser5Bean user5Bean = new AnnotationUser5Bean();
            user5Bean.setUserId(1);
            user5Bean.setAge(0);
            user5Bean.setVersion(0);
            userMapper.updateById(user5Bean);
     
            // 修改數據
            for (int i = 0; i < 10; i++) {
                System.out.println("第 " + (i + 1) + " 次修改數據");
                final CountDownLatch countDownLatch = new CountDownLatch(2);
                modifyUser(countDownLatch, "My-Thread-A", 1);
                modifyUser(countDownLatch, "My-Thread-B", 1);
                countDownLatch.await();
                Thread.sleep(100L);
            }
        }
     
        private void modifyUser(final CountDownLatch countDownLatch, String threadName, int userId) {
            Thread t = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        String threadName = Thread.currentThread().getName();
                        try {
                            AnnotationUser5Bean userBean = userMapper.selectById(userId);
                            if (null == userBean) {
                                return;
                            }
                            AnnotationUser5Bean newBean = new AnnotationUser5Bean();
                            newBean.setName(userBean.getName());
                            newBean.setSex(userBean.getSex());
                            newBean.setAge(userBean.getAge() + 1);
                            newBean.setUserId(userBean.getUserId());
                            newBean.setVersion(userBean.getVersion());
                            int result = userMapper.updateById(newBean);
                            System.out.println("result=" + result + " ==> " + userBean);
                        } catch (Exception e) {
                            System.err.println(threadName + " " + e.getMessage());
                        }
                    } finally {
                        countDownLatch.countDown();
                    }
                }
            });
            t.setName(threadName);
            t.start();
        }
     
    }

    在運行上面代碼之前,我們數據庫中的記錄值如下:

    user_idnamesexageversion
    1測試00

    運行上面程序,數據庫記錄如下:

    user_idnamesexageversion
    1測試016

    1.上面代碼將執行10次循環操作,每次操作啟動兩個線程(線程 A 和 線程 B)去修改用戶數據。

    2.如果數據沒有任何沖突,則用戶的年齡應該是 20。但是上面程序運行完成后年齡為 16

    3.這就說明,在線程運行的時候,可能A 剛好修改了version,并沒有執行完,就到B線程了,就導致B線程修改失敗

    感謝各位的閱讀,以上就是“MybatisPlus中@Version注解如何使用”的內容了,經過本文的學習后,相信大家對MybatisPlus中@Version注解如何使用這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    建阳市| 许昌市| 申扎县| 尖扎县| 武山县| 大姚县| 兴化市| 五原县| 永平县| 新郑市| 曲麻莱县| 香格里拉县| 白水县| 上思县| 桃江县| 永清县| 龙岩市| 北流市| 神农架林区| 苏尼特左旗| 紫阳县| 水城县| 静海县| 遵化市| 齐齐哈尔市| 长垣县| 东莞市| 炎陵县| 萍乡市| 平顺县| 永和县| 黔东| 镇宁| 来凤县| 化隆| 张家界市| 共和县| 西平县| 新平| 古田县| 安多县|