java jpa 异步编程_异步处理时的JPA
java jpa 異步編程
幾年前,在Java世界中,幾乎顯而易見的是,每個“企業”類項目都需要JPA與數據庫進行通信。 JPA是Joel Spolsky描述的“ 泄漏抽象 ”的完美示例。 剛開始時很棒而又容易,但是最后很難調整和限制。 對于許多參與數據訪問層的后端開發人員而言,日常工作是黑客并直接使用緩存,刷新和本機查詢。 有足夠的問題和變通辦法來寫一本專門的書“面向黑客的JPA”,但是在本文中,我將僅關注并發實體處理。
讓我們假設這種情況:我們有一個Person實體,該實體在某些業務流程中由某些服務更新。
@Entity public class Person {@Id@GeneratedValueprivate Long id;private String uuid = UUID.randomUUID().toString();private String firstName;private String lastName;// getters and setters}為了忽略任何域的復雜性,我們正在談論更新此人的名字和姓氏。 我們可以想象代碼如下:
firstNameUpdater.update(personUuid, "Jerry"); lastNameUpdater.update(personUuid, "Newman");經過一段時間的業務決定,這兩個元素的更新都花了太長時間,因此減少持續時間成為了頭等大事。 當然,有很多不同的方法可以做到這一點,但讓我們假設,這種特殊情況并發將解決我們的難題。 這似乎很容易-只需使用Spring和voilà中的@Async注釋我們的服務方法即可解決問題。 真? 根據樂觀鎖定機制的使用,我們這里有兩個可能的問題。
- 使用樂觀鎖定,幾乎可以肯定,我們將從其中一種更新方法中獲得OptimisticLockException-一種將排名第二的方法。 與根本不使用樂觀鎖定相比,這種情況更好。
- 沒有版本控制,所有更新將毫無例外地完成,但是從數據庫加載更新的實體后,我們將僅發現一個更改。 為什么會這樣呢? 兩種方法都更新了不同的字段! 為什么第二筆交易覆蓋了其他更新? 由于泄漏的抽象:)
我們知道,Hibernate正在跟蹤對我們實體所做的更改(稱為臟檢查)。 但是為了減少編譯查詢所需的時間,默認情況下,它在更新查詢中包括所有字段,而不是僅包含已更改的字段。 看起來很奇怪? 幸運的是,我們可以將Hibernate配置為以其他方式工作,并根據實際更改的值生成更新查詢。 可以使用@DynamicUpdate批注啟用它。 這可以看作是部分更新問題的解決方法,但是您必須記住這是一個折衷方案。 現在,此實體的每次更新都比以前更耗時。
現在讓我們回到樂觀鎖定的情況。 坦白地說,我們想要做的通常與這種鎖定的想法相反,這種鎖定假定實體不會同時進行任何修改,并且當這種情況發生時會引發異常。 現在我們肯定要進行并發修改! 作為一種快速的解決方法,我們可以從鎖定機制中排除這兩個字段( firstName和lastName )。 可以通過在每個字段上添加@OptimisticLock(excluded = true)來實現。 現在,更新名稱將不會觸發版本增加-它將保持不變,這當然可能是造成許多麻煩且難以發現一致性問題的原因。
最后但并非最不重要的解決方案是旋轉更改。 要使用它,我們必須用循環包裝更新邏輯,當OptimisticLock發生時,該邏輯在事務處理時更新。 效果越好,進程中涉及的線程越少。 所有這些解決方案的源代碼都可以在我的GitHub的jpa-async-examples存儲庫中找到 。 只是探索提交。
等待-仍然沒有適當的解決方案? 實際上沒有。 由于使用了JPA,我們對并發修改問題的簡單解決方案不屑一顧。 當然,我們可以重塑我們的應用程序以引入一些基于事件的方法,但是上面我們仍然有JPA。 如果我們使用域驅動設計,則嘗試通過使用OPTIMISTIC_FORCE_INCREMENT鎖定來關閉整個聚合,只是為了確保更改復合實體或向集合中添加元素會更新整個聚合,因為它應保護不變量。 那么,為什么不使用任何直接訪問工具,例如JOOQ或JdbcTemplate呢? 這個主意很棒,但不幸的是,不能與JPA同時使用。 JOOQ所做的任何修改都不會自動傳播到JPA,這意味著會話或緩存可能包含過時的值。
為了正確解決這種情況,我們應該將此上下文提取到單獨的元素中,例如new table,它將直接由JOOQ處理。 您可能已經注意到,在SQL中進行這種并發更新非常容易:
update person set first_name = "Jerry" where uuid = ?;使用JPA抽象,它變成了非常復雜的任務,需要對Hibernate行為以及實現內部有深刻的了解。 綜上所述,我認為JPA沒有遵循“React式”方法。 它是為解決某些問題而構建的,但是目前我們提出了不同的問題,而在許多應用程序中,持久性并不是其中之一。
翻譯自: https://www.javacodegeeks.com/2015/11/jpa-in-case-of-asynchronous-processing.html
java jpa 異步編程
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的java jpa 异步编程_异步处理时的JPA的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: php cdi_本机CDI限定词:@An
- 下一篇: 广州口罩怎么申请(广州口罩备案)