国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

解放生產力orm并發(fā)更新下應該這么處理求求你別再用UpdateById了

這篇具有很好參考價值的文章主要介紹了解放生產力orm并發(fā)更新下應該這么處理求求你別再用UpdateById了。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

解放生產力orm并發(fā)更新下應該這么處理求求你別再用UpdateById了

背景

很多時候為了方便我們都采用實體對象進行前后端的數據交互,然后為了便捷開發(fā)我們都會采用DTO對象進行轉換為數據庫對象,然后調用UpdateById將變更后的數據存入到數據庫內,這樣的一個做法有什么問題呢,如果你的系統(tǒng)并發(fā)量特別少甚至沒有并發(fā)量那么這么做是沒什么關系的無可厚非,但是如果你的系統(tǒng)有并發(fā)量那么在某些情況下會有嚴重的問題.

案例1

現在我們有一條待審核記錄,其中status 0表示待提交, 1表示待審核

id name status description
1 記錄1 0 我是備注

假設有兩個用戶,A用戶想對當前記錄的description字段進行修改,B用戶想對當前記錄進行提交

用戶請求

/api/update

  • 用戶A: {"id":1,"name":"記錄1","status":0,"description":"修改后的備注"}
  • 用戶B: {"id":1,"name":"記錄1","status":1,"description":"我是備注 "}

修改接口

A用戶偽代碼

Entity entity = entityMapper.selectOne(1);//A1
//查詢結果{"id":1,"name":"記錄1","status":0,"description":"我是備注'"}
if(status.待審核!=entity.status){//A2
  throw new BusinessException("當前記錄無法修改");
}
BeanUtil.copyProperties(request,entity);//A3
entityMapper.updateById(entity);//A4
-- update table set name='記錄1',status=0,description='修改后的備注' where id=1

提交接口

B用戶偽代碼

Entity entity = entityMapper.selectOne(1);//B1
//查詢結果{"id":1,"name":"記錄1","status":0,"description":"我是備注'"}
if(status.待審核!=entity.status){//B2
  throw new BusinessException("當前記錄無法提交");
}
entity.status=status.待審核;//B3
entityMapper.updateById(entity);//B4
-- update table set name='記錄1',status=1,description='我是備注', where id=1

提交請求

A1=>A2=>A3=>B1=>B2=>B3=>B4=>A4
加入并發(fā)情況下那么針對當前記錄我們生成的兩個操作因為沒有考慮并發(fā)問題基于上述執(zhí)行順序,最終數據庫的記錄將會被A4覆蓋也就是提交失敗,那么如果提交審核會觸發(fā)一些事件那么就就會有嚴重的問題產生,操作將會變得不是冪等。

解決方案

樂觀鎖

首先我們修改表結構添加版本號字段

id name status description version
1 記錄1 0 我是備注 1

A4和B4的執(zhí)行sql改為orm支持的樂觀鎖模式

-- A4
update table set name='記錄1',status=0,description='修改后的備注',version=2 where id=1 and version=1

-- B4
update table set name='記錄1',status=1,description='我是備注',version=2 where id=1 and version=1

因為A4和B4兩條記錄只有一條記錄可以生效,所以另一條語句肯定返回受影響行數為0.對于返回為0的操作可以告知用戶端操作失敗請重試。

這種方式看著看著很美好但是也是有一定的缺點的,就是他是樂觀鎖強串行化,針對一些不必要的字段其實大部分的時候我們完全可以采取后覆蓋模式比如修改name,修改description,但是因為樂觀鎖的存在導致我們的并發(fā)粒度變粗所以是否使用樂觀鎖需要進行一個取舍。

分布式鎖

通過在請求外部也就是A1-A4和B1-B4外部進行l(wèi)ock包裹,讓兩個執(zhí)行變成串行化,可以用id:1作為分布式鎖的key,加入A先執(zhí)行那么B執(zhí)行后可以提交,加入B先執(zhí)行那么A就會報錯,缺點也很明顯需要將對應記錄的任何操作都進行分布式鎖進行處理。需要掌握好鎖的粒度和管理,如果出現其他業(yè)務操作中涉及到當前記錄的修改那么分布式鎖又會遇到很多問題,在單一環(huán)境下分布式鎖可以解決,但是大部分情況下并不是用在這個場景下。

以判斷條件為樂觀鎖

既然樂觀鎖有粒度太粗導致并發(fā)度太低,那么可以選擇性不要一刀切,我們以狀態(tài)來作為樂觀鎖更新數據

-- A4
update table set name='記錄1',status=0,description='修改后的備注' where id=1 and status=0//status=0是因為我們查到的是0

-- B4
update table set name='記錄1',status=1,description='我是備注' where id=1  and status=0//status=0是因為我們查到的是0

這種方式我們解決了name或者description這些無關順序痛癢的更新粒度,使其更新其余字段并發(fā)度大大提高,大家可以多個線程一起更新name或者description都是不會出現樂觀鎖的錯誤。

雖然我們解決了普通字段的更新修改但是針對部分關鍵字段的更新如果是整個對象更新依然會有問題,那么又回到了樂觀鎖是一個比較好的處理方式,比如stock_num字段

easy-query

我們來看看如果在easy-query下我們分別如何實現上述功能,首先我們還是在之前的solon項目中進行代碼添加,

@Data
@Table("test_update")
public class TestUpdateEntity {
    @Column(primaryKey = true)
    private String id;
    private String name;
    private Integer status;
    private String description;
}

//添加測試數據

  TestUpdateEntity testUpdateEntity = new TestUpdateEntity();
  testUpdateEntity.setId("1");
  testUpdateEntity.setName("測試1");
  testUpdateEntity.setStatus(0);
  testUpdateEntity.setDescription("描述信息");
  easyQuery.insertable(testUpdateEntity).executeRows();
  return "ok";

審核普通更新

一般而言我們會先選擇查詢對象,然后判斷狀態(tài)然后將dto請求賦值給對象,之后更新對象


    @Mapping(value = "/testUpdate2",method = MethodType.POST)
    public String testUpdate2(@Validated TestUpdate2Rquest request){
        TestUpdateEntity testUpdateEntity = easyQuery.queryable(TestUpdateEntity.class)
                .whereById(request.getId()).firstNotNull("未找到對應的記錄");
        if(!testUpdateEntity.getStatus().equals(0)){
            return "當前狀態(tài)不是0";
        }
        BeanUtil.copyProperties(request,testUpdateEntity);
        testUpdateEntity.setStatus(1);
        easyQuery.updatable(testUpdateEntity).executeRows();
        return "ok";
    }

解放生產力orm并發(fā)更新下應該這么處理求求你別再用UpdateById了

==> Preparing: SELECT `id`,`name`,`status`,`description` FROM `test_update` WHERE `id` = ? LIMIT 1
==> Parameters: 1(String)
<== Time Elapsed: 22(ms)
<== Total: 1

==> Preparing: UPDATE `test_update` SET `name` = ?,`status` = ?,`description` = ? WHERE `id` = ?
==> Parameters: 測試1(String),1(Integer),123(String),1(String)
<== Total: 1

我們看到這邊更新將status由0改成了1,雖然我們中間做了一次是否為0的判斷,但是在并發(fā)環(huán)境下這么更新是有問題的,而且這邊我們僅更新了descriptionstatus字段缺把name字段也更新了

審核并發(fā)更新

首先我們改造一下代碼,在請求方法上添加了對應的注解@EasyQueryTrack又因為我們配置了默認開啟追蹤所以僅需要查詢數據庫對象既可以追蹤數據


    //自動追蹤差異更新 需要開啟default-track: true如果沒開啟那么就使用`asTracking`啟用追蹤
    @EasyQueryTrack 
    @Mapping(value = "/testUpdate3",method = MethodType.POST)
    public String testUpdate3(@Validated TestUpdate2Rquest request){
        TestUpdateEntity testUpdateEntity = easyQuery.queryable(TestUpdateEntity.class)
                //.asTracking() //如果配置文件默認選擇追蹤那么只需要添加 @EasyQueryTrack 注解
                .whereById(request.getId())
                .firstNotNull("未找到對應的記錄");
        if(!testUpdateEntity.getStatus().equals(0)){
            return "當前狀態(tài)不是0";
        }
        BeanUtil.copyProperties(request,testUpdateEntity);
        testUpdateEntity.setStatus(1);
        easyQuery.updatable(testUpdateEntity)
                //指定更新條件為主鍵和status字段
                .whereColumns(o->o.columnKeys().column(TestUpdateEntity::getStatus))
                .executeRows(1,"當前狀態(tài)不是0");//如果更新返回的受影響函數不是1,那么就拋出錯誤,當然你也可以獲取返回結果自行處理
        return "ok";
    }

解放生產力orm并發(fā)更新下應該這么處理求求你別再用UpdateById了

==> Preparing: SELECT `id`,`name`,`status`,`description` FROM `test_update` WHERE `id` = ? LIMIT 1
==> Parameters: 1(String)
<== Time Elapsed: 23(ms)
<== Total: 1

==> Preparing: UPDATE `test_update` SET `status` = ?,`description` = ? WHERE `id` = ? AND `status` = ?
==> Parameters: 1(Integer),123(String),1(String),0(Integer)
<== Total: 1

更新條件自動感知需要更新的列,不會無腦全更新,并且支持簡單的配置支持當前status并發(fā)更新,會自動在where上帶上原來的值,并且在set處更新為新值,整個更新條件對于并發(fā)情況下的處理變得非常簡單

樂觀鎖

@Data
@Table("test_update_version")
public class TestUpdateVersionEntity {
    @Column(primaryKey = true)
    private String id;
    private String name;
    private Integer status;
    private String description;
    @Version(strategy = VersionUUIDStrategy.class)
    private String version;
}

//初始化數據
  TestUpdateVersionEntity testUpdateVersionEntity = new TestUpdateVersionEntity();
  testUpdateVersionEntity.setId("1");
  testUpdateVersionEntity.setName("測試1");
  testUpdateVersionEntity.setStatus(0);
  testUpdateVersionEntity.setDescription("描述信息");
  testUpdateVersionEntity.setVersion(UUID.randomUUID().toString().replaceAll("-",""));
  easyQuery.insertable(testUpdateVersionEntity).executeRows();



==> Preparing: INSERT INTO `test_update_version` (`id`,`name`,`status`,`description`,`version`) VALUES (?,?,?,?,?)
==> Parameters: 1(String),測試1(String),0(Integer),描述信息(String),0603b2e00a1d4b869d13cf974a5cc885(String)
<== Total: 1

審核樂觀鎖


    @Mapping(value = "/testUpdate2",method = MethodType.POST)
    public String testUpdate2(@Validated TestUpdate2Rquest request){
        TestUpdateVersionEntity testUpdateVersionEntity = easyQuery.queryable(TestUpdateVersionEntity.class)
                .whereById(request.getId()).firstNotNull("未找到對應的記錄");
        if(!testUpdateVersionEntity.getStatus().equals(0)){
            return "當前狀態(tài)不是0";
        }
        BeanUtil.copyProperties(request,testUpdateVersionEntity);
        testUpdateVersionEntity.setStatus(1);
        easyQuery.updatable(testUpdateVersionEntity).executeRows();
        return "ok";
    }

解放生產力orm并發(fā)更新下應該這么處理求求你別再用UpdateById了


==> Preparing: SELECT `id`,`name`,`status`,`description`,`version` FROM `test_update_version` WHERE `id` = ? LIMIT 1
==> Parameters: 1(String)
<== Time Elapsed: 16(ms)
<== Total: 1


==> Preparing: UPDATE `test_update_version` SET `name` = ?,`status` = ?,`description` = ?,`version` = ? WHERE `version` = ? AND `id` = ?
==> Parameters: 測試1(String),1(Integer),123(String),cf6c2f3106b24aba965bb4cc54235076(String),0603b2e00a1d4b869d13cf974a5cc885(String),1(String)
<== Total: 1

雖然我們采用了樂觀鎖但是還是會出現全字段更新的情況,所以這邊再次使用差異更新來實現


    @EasyQueryTrack
    @Mapping(value = "/testUpdate3",method = MethodType.POST)
    public String testUpdate3(@Validated TestUpdate2Rquest request){
        TestUpdateVersionEntity testUpdateVersionEntity = easyQuery.queryable(TestUpdateVersionEntity.class)
                .whereById(request.getId()).firstNotNull("未找到對應的記錄");
        if(!testUpdateVersionEntity.getStatus().equals(0)){
            return "當前狀態(tài)不是0";
        }
        BeanUtil.copyProperties(request,testUpdateVersionEntity);
        testUpdateVersionEntity.setStatus(1);
        easyQuery.updatable(testUpdateVersionEntity).executeRows();
        return "ok";
    }

解放生產力orm并發(fā)更新下應該這么處理求求你別再用UpdateById了


==> Preparing: UPDATE `test_update_version` SET `status` = ?,`description` = ?,`version` = ? WHERE `version` = ? AND `id` = ?
==> Parameters: 1(Integer),1234(String),7e96f217bc13451c9d10a8fba50780a6(String),cf6c2f3106b24aba965bb4cc54235076(String),1(String)
<== Total: 1

使用追蹤查詢僅更新我們需要更新的字段easy-query一款為開發(fā)者而生的orm框架,擁有非常完善的功能且支持非常易用的功能,讓你在編寫業(yè)務時可以非常輕松的實現并發(fā)操作,哪怕沒有樂觀鎖。

最后

看到這邊您應該已經知道了solon國產框架的簡潔和easy-query的便捷,如果本篇文章對您有幫助或者您覺得還行請給我一個星星表示支持謝謝
當前項目地址demo https://gitee.com/xuejm/solon-encrypt

easy-query

文檔地址 https://xuejm.gitee.io/easy-query-doc/

GITHUB地址 https://github.com/xuejmnet/easy-query

GITEE地址 https://gitee.com/xuejm/easy-query

solon

文檔地址 https://xuejm.gitee.io/easy-query-doc/

GITHUB地址 https://github.com/noear/solon

GITEE地址 https://gitee.com/noear/solon文章來源地址http://www.zghlxwxcb.cn/news/detail-663489.html

到了這里,關于解放生產力orm并發(fā)更新下應該這么處理求求你別再用UpdateById了的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!

本文來自互聯(lián)網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • 有沒有一種支持對象建模、數據庫建模和低代碼能力的工具,用來解放程序員生產力呢?

    有沒有一種支持對象建模、數據庫建模和低代碼能力的工具,用來解放程序員生產力呢?

    1. 簡介 作為一個程序員,很多時候在面對項目開發(fā)工期短、任務重、功能復雜、壓力大,同時還得迎合領導或者甲方的要求提供研發(fā)設計文檔時,往往很苦惱,因為隨著軟件項目的迭代,很難保持輸出與代碼一致的數據模型和架構模式相關設計圖,而且還要花費大量時間去繪

    2024年02月06日
    瀏覽(95)
  • Visual Studio2022史詩級更新,增加多個提高生產力的功能

    Visual Studio2022史詩級更新,增加多個提高生產力的功能

    Visual Studio 2022發(fā)布了17.7x版,這次更新中,增加多個提高生產力的功能以及性能進一步改進。 如果要體驗新功能,需要將Visual Studio 2022的版本升級到 17.7 及以上 下面我們看看新增的功能以及改進的功能! 話說,終于可以在VS里進行文件比較了。而在VS中進行文件比較非常簡單

    2024年02月11日
    瀏覽(23)
  • 提高開發(fā)生產力 - 生產力指南篇(之一)

    提高開發(fā)生產力 - 生產力指南篇(之一)

    自行打開 IDEA - help - My productity (舊版本叫Productity Guide) , idea統(tǒng)計的生產力特性,熟練掌握這些特性,開發(fā)事半功倍 Tips: 大部分特性包含快捷鍵炒作,快捷鍵因為WIN MAC或者idea鍵位不同,然后IDEA提供了多種版本快捷鍵,所以選擇自己適合的即可(sublime /eclipse/vs等),如果你沒

    2023年04月23日
    瀏覽(25)
  • 文檔批量添加文字,高效提升生產力

    文檔批量添加文字,高效提升生產力

    從簡單的記事本到復雜的項目報告,我們每天都在與各種文本文檔打交道。但你是否曾為批量處理這些文檔而感到煩惱?是否曾為重復、繁瑣的操作而感到力不從心?今天,我要為大家介紹一款強大的軟件——首助編輯高手,幫助您輕松解決這些問題,讓您的生產力瞬間提升

    2024年01月20日
    瀏覽(22)
  • AIGC—— 內容生產力革命的起點

    AIGC—— 內容生產力革命的起點

    作者簡介:一名云計算網絡運維人員、每天分享網絡與運維的技術與干貨。? ?座右銘:低頭趕路,敬事如儀 個人主頁:網絡豆的主頁?????? 目錄 ?前言 一.AIGC 1.什么是AIGC? ?2.AIGC有哪些優(yōu)勢與挑戰(zhàn) (1)優(yōu)勢 (2)挑戰(zhàn) 二.AIGC連續(xù)爆火 1.AIGC連續(xù)爆火 2. AIGC定義 三.AIG

    2024年02月08日
    瀏覽(30)
  • AIGC - 生產力新工具 Copilot

    AIGC - 生產力新工具 Copilot

    https://github.com/features/copilot Copilot的主要功能包括: 代碼補全和提示:Copilot會根據上下文,智能提示您可能需要的變量,函數,參數等。 快速生成代碼:Copilot可以快速生成if語句,for循環(huán),類定義,函數定義等代碼模板。 代碼優(yōu)化:Copilot會檢測代碼并提供重構方案,比如提取方法,調整變量

    2024年02月01日
    瀏覽(25)
  • PyCharm十大提高生產力的插件

    PyCharm十大提高生產力的插件

    PyCharm是一個非常流行的Python開發(fā)IDE。除了支持Python語言,PyCharm還支持其他流行的語言,如C、C++、JavaScript等。PyCharm被廣泛使用,是因為它擁有許多方便而實用的插件,這些插件能夠顯著提高開發(fā)者的生產力。下面我們將介紹十大提高生產力的插件。 PyCharm IDE Theme Plugin 一個漂

    2024年02月07日
    瀏覽(20)
  • AIGC生產力神器 學習必用

    AIGC生產力神器 學習必用

    ??最近AI領域備受關注,作為熱愛學習的大學生肯定不能錯過,分享一個我最近很愛看的AI社區(qū),這里面基本涵蓋所有AI軟件及知識 ?? ? ??工具涵蓋的分類有: 國際工具導航、搜索引擎、文本寫作、智能翻譯、聊天機器人、內容檢測器、辦公工具、營銷工具、財務事務、語音

    2024年02月12日
    瀏覽(18)
  • 如何讓數據成為企業(yè)的生產力?

    如何讓數據成為企業(yè)的生產力?

    為什么有的企業(yè)投入大量的人力、物力、財力做數字化轉型建設最終做了個寂寞!企業(yè)領導沒看到數字化的任何價值! 如果要問企業(yè)數字化轉型建設最核心的價值體現是什么,大部分人都會說是: 數據! 然而,不同的人、不同的場景對數據的理解是不同的。 在一般技術人員

    2024年02月09日
    瀏覽(20)
  • ChatGPT生產力|實用指令(prompt)

    ChatGPT生產力|實用指令(prompt)

    ????????GPT已經成為一個不可或缺的科研生產力了,但是大多數人只知曉采用直接提問、持續(xù)追問以及細節(jié)展開的方式來查閱相關資料,本文側重于探討“限定場景+限定角色+限定主題”、“可持續(xù)追問+細節(jié)展開”等多種方式來獲取更多信息,幫人們解決更多問題。 ???

    2024年02月07日
    瀏覽(22)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包