日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

异步处理时的JPA

發(fā)布時間:2023/12/3 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 异步处理时的JPA 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

幾年前,在Java世界中,幾乎所有的“企業(yè)”類項目都需要JPA與數(shù)據(jù)庫進(jìn)行通信,這幾乎是顯而易見的。 JPA是Joel Spolsky描述的“ 泄漏抽象 ”的完美示例。 剛開始時很棒而又容易,但最后很難調(diào)整和限制。 對于許多參與數(shù)據(jù)訪問層的后端開發(fā)人員而言,日常工作是黑客并直接使用緩存,刷新和本機(jī)查詢。 有足夠的問題和變通辦法來寫一本專門的書“面向黑客的JPA”,但是在本文中,我將只關(guān)注并發(fā)實體處理。

讓我們假設(shè)這種情況:我們有一個Person實體,該實體在某些業(yè)務(wù)流程中由某些服務(wù)更新。

@Entity public class Person {@Id@GeneratedValueprivate Long id;private String uuid = UUID.randomUUID().toString();private String firstName;private String lastName;// getters and setters}

為了忽略任何域的復(fù)雜性,我們正在談?wù)摳麓巳说拿趾托帐稀?我們可以想象代碼如下:

firstNameUpdater.update(personUuid, "Jerry"); lastNameUpdater.update(personUuid, "Newman");

經(jīng)過一段時間的業(yè)務(wù)決定,更新兩個元素都需要花費太長時間,因此縮短工期成為當(dāng)務(wù)之急。 當(dāng)然,有很多不同的方法可以做到這一點,但讓我們假設(shè),這種特殊情況并發(fā)將解決我們的難題。 這似乎很容易-只需使用Spring和voilà中的@Async注釋我們的服務(wù)方法即可解決問題。 真? 根據(jù)樂觀鎖定機(jī)制的使用,我們這里有兩個可能的問題。

  • 使用樂觀鎖定,幾乎可以肯定,我們將從其中一種更新方法中獲得OptimisticLockException-一種將排名第二的方法。 與根本不使用樂觀鎖定相比,這種情況更好。
  • 沒有版本控制,所有更新將毫無例外地完成,但是從數(shù)據(jù)庫加載更新的實體后,我們將僅發(fā)現(xiàn)一個更改。 為什么會這樣呢? 兩種方法都更新了不同的字段! 為什么第二筆交易覆蓋了其他更新? 由于泄漏的抽象:)

我們知道,Hibernate正在跟蹤對我們實體所做的更改(稱為臟檢查)。 但是為了減少編譯查詢所需的時間,默認(rèn)情況下,它在更新查詢中包括所有字段,而不是僅包含已更改的字段。 看起來很奇怪? 幸運的是,我們可以配置Hibernate以其他方式工作,并根據(jù)實際更改的值生成更新查詢。 可以使用@DynamicUpdate批注啟用它。 這可以被視為解決部分更新問題的方法,但是您必須記住這是一個折衷方案。 現(xiàn)在,此實體的每次更新都比以前更耗時。

現(xiàn)在讓我們回到樂觀鎖定的情況。 老實說,我們想要做的通常與這種鎖定的想法相反,這種鎖定假定可能不會對該實體進(jìn)行任何并發(fā)修改,并且在發(fā)生這種情況時會引發(fā)異常。 現(xiàn)在我們肯定要進(jìn)行并發(fā)修改! 作為一種快速的解決方法,我們可以從鎖定機(jī)制中排除這兩個字段( firstName和lastName )。 可以通過在每個字段上添加@OptimisticLock(excluded = true)來實現(xiàn)。 現(xiàn)在,更新名稱將不會觸發(fā)版本增加-它將保持不變,這當(dāng)然可以成為許多令人討厭且難以發(fā)現(xiàn)一致性問題的來源。
最后但并非最不重要的解決方案是旋轉(zhuǎn)更改。 要使用它,我們必須將更新邏輯包裝在循環(huán)中,并在發(fā)生OptimisticLock時在事務(wù)處理時進(jìn)行更新。 效果越好,進(jìn)程中涉及的線程越少。 所有這些解決方案的源代碼都可以在我的GitHub的jpa-async-examples存儲庫中找到 。 只是探索提交。

等待-仍然沒有適當(dāng)?shù)慕鉀Q方案? 實際上沒有。 僅由于使用了JPA,我們才對并發(fā)修改問題的簡單解決方案不了解。 當(dāng)然,我們可以重塑我們的應(yīng)用程序以引入一些基于事件的方法,但是上面我們?nèi)匀挥蠮PA。 如果我們使用域驅(qū)動設(shè)計,則嘗試通過使用OPTIMISTIC_FORCE_INCREMENT鎖定來關(guān)閉整個聚合,只是要確保更改復(fù)合實體或向集合中添加元素會更新整個聚合,因為它可以保護(hù)不變量。 那么,為什么不使用任何直接訪問工具,例如JOOQ或JdbcTemplate呢? 這個主意很棒,但不幸的是,不能與JPA同時使用。 JOOQ所做的任何修改都不會自動傳播到JPA,這意味著會話或緩存可能包含過時的值。

為了正確解決這種情況,我們應(yīng)該將此上下文提取到單獨的元素中,例如new table,它將直接由JOOQ處理。 您可能已經(jīng)注意到,在SQL中進(jìn)行這種并發(fā)更新非常容易:

update person set first_name = "Jerry" where uuid = ?;

使用JPA抽象,它變成了非常復(fù)雜的任務(wù),需要對Hibernate行為以及實現(xiàn)內(nèi)部進(jìn)行真正的深入了解。 綜上所述,我認(rèn)為JPA沒有遵循“反應(yīng)式”方法。 它是為解決某些問題而構(gòu)建的,但是目前我們提出了不同的問題,而在許多應(yīng)用程序中,持久性并不是其中之一。

翻譯自: https://www.javacodegeeks.com/2015/11/jpa-in-case-of-asynchronous-processing.html

總結(jié)

以上是生活随笔為你收集整理的异步处理时的JPA的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。