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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Hibernate应用程序级可重复读取

發布時間:2023/12/3 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Hibernate应用程序级可重复读取 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

介紹

在我以前的文章中,我描述了應用程序級事務如何為長時間的對話提供合適的并發控制機制。

所有實體都在Hibernate會話的上下文中加載,充當事務后寫式緩存 。

Hibernate持久性上下文可以包含給定實體的一個引用和一個引用。 一級緩存可確保會話級可重復讀取。

如果對話跨越多個請求,我們可以進行應用程序級的可重復讀取。 長時間的對話本質上是有狀態的,因此我們可以選擇分離的對象或長期的持久性上下文 。 但是,應用程序級可重復讀取需要應用程序級并發控制策略,例如樂觀鎖定。

抓住

但是這種行為有時可能被證明是出乎意料的。

如果您的Hibernate會話已經加載了給定的實體,那么任何后續的實體查詢(JPQL / HQL)都將返回完全相同的對象引用(不考慮當前加載的數據庫快照):

在此示例中,我們可以看到第一級緩存可防止覆蓋已加載的實體。 為了證明這種行為,我提出了以下測試案例:

final ExecutorService executorService = Executors.newSingleThreadExecutor();doInTransaction(new TransactionCallable<Void>() {@Overridepublic Void execute(Session session) {Product product = new Product();product.setId(1L);product.setQuantity(7L);session.persist(product);return null;} });doInTransaction(new TransactionCallable<Void>() {@Overridepublic Void execute(Session session) {final Product product = (Product) session.get(Product.class, 1L);try {executorService.submit(new Callable<Void>() {@Overridepublic Void call() throws Exception {return doInTransaction(new TransactionCallable<Void>() {@Overridepublic Void execute(Session _session) {Product otherThreadProduct = (Product) _session.get(Product.class, 1L);assertNotSame(product, otherThreadProduct);otherThreadProduct.setQuantity(6L);return null;}});}}).get();Product reloadedProduct = (Product) session.createQuery("from Product").uniqueResult();assertEquals(7L, reloadedProduct.getQuantity());assertEquals(6L, ((Number) session.createSQLQuery("select quantity from Product where id = :id").setParameter("id", product.getId()).uniqueResult()).longValue());} catch (Exception e) {fail(e.getMessage());}return null;} });

該測試案例清楚地說明了實體查詢和SQL預測之間的區別。 盡管SQL查詢投影總是加載最新的數據庫狀態,但是實體查詢結果由第一級緩存管理,以確保會話級可重復讀取。

解決方法1:如果您的用例要求重新加載最新的數據庫實體狀態,則只需刷新有問題的實體。

解決方法2:如果希望將某個實體與Hibernate一級緩存解除關聯,則可以輕松地將其退出 ,因此下一個實體查詢可以使用最新的數據庫實體值。

超越偏見

休眠是一種手段,而不是目標。 數據訪問層既需要讀取又需要寫入,而普通的JDBC和Hibernate都不是一種千篇一律的解決方案。 數據知識堆棧更適合于獲取最多的數據讀取查詢和寫入DML語句。

盡管原生SQL仍然是事實上的關系數據讀取技術,但是Hibernate在寫入數據方面表現出色。 Hibernate是一個持久性框架,您永遠不要忘記這一點。 如果計劃將更改傳播回數據庫,則加載實體是有意義的。 您不需要加載用于顯示只讀視圖的實體,在這種情況下,SQL投影是更好的選擇。

會話級可重復讀取可防止并發寫入場景中的更新丟失,因此,有充分的理由說明實體不會自動刷新。 也許我們選擇了手動刷新臟屬性 ,并且自動刷新實體可能會覆蓋同步的未決更改。

設計數據訪問模式并不是一件容易的事,值得投資堅實的集成測試基礎。為避免任何未知行為,我強烈建議您驗證所有自動生成的SQL語句,以證明其有效性和效率 。

  • 代碼可在GitHub上獲得 。

翻譯自: https://www.javacodegeeks.com/2014/10/hibernate-application-level-repeatable-reads.html

總結

以上是生活随笔為你收集整理的Hibernate应用程序级可重复读取的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。