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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Hibernate READ_ONLY CacheConcurrencyStrategy如何工作

發布時間:2023/12/3 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Hibernate READ_ONLY CacheConcurrencyStrategy如何工作 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

介紹

正如我前面所解釋的 ,企業的高速緩存需要勤奮。 由于數據在數據庫( 記錄系統 )和緩存層之間重復,因此我們需要確保兩個單獨的數據源不會分開。

如果緩存的數據是不可變的(數據庫和緩存都無法修改它),我們可以安全地對其進行緩存,而不必擔心任何一致性問題。 只讀數據始終是應用程序級緩存的理想選擇,可以在不放松一致性保證的情況下提高讀取性能。

只讀二級緩存

為了測試只讀二級緩存策略,我們將使用以下域模型:

存儲庫是根實體,是任何Commit實體的父代。 每個提交都有一個“ 更改”組件(可嵌入的值類型)列表。

所有實體都緩存為只讀元素:

@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY )

持久實體

只讀二級緩存使用一種直讀緩存策略,在獲取時會緩存實體。

doInTransaction(session -> {Repository repository = new Repository("Hibernate-Master-Class");session.persist(repository); });

當一個實體持久化時,只有數據庫包含該實體的副本。 首次獲取實體時,記錄系統將傳遞到緩存層。

@Test public void testRepositoryEntityLoad() {LOGGER.info("Read-only entities are read-through");doInTransaction(session -> {Repository repository = (Repository) session.get(Repository.class, 1L);assertNotNull(repository);});doInTransaction(session -> {LOGGER.info("Load Repository from cache");session.get(Repository.class, 1L);}); }

此測試生成輸出:

--Read-only entities are read-throughSELECT readonlyca0_.id AS id1_2_0_,readonlyca0_.NAME AS name2_2_0_ FROM repository readonlyca0_ WHERE readonlyca0_.id = 1 --JdbcTransaction - committed JDBC Connection--Load Repository from cache--JdbcTransaction - committed JDBC Connection

將實體加載到二級緩存后,緩存將為隨后的所有調用提供服務,從而繞過數據庫。

更新實體

只讀緩存條目不允許更新。 任何此類嘗試最終都會引發異常:

@Test public void testReadOnlyEntityUpdate() {try {LOGGER.info("Read-only cache entries cannot be updated");doInTransaction(session -> {Repository repository = (Repository) session.get(Repository.class, 1L);repository.setName("High-Performance Hibernate");});} catch (Exception e) {LOGGER.error("Expected", e);} }

運行此測試將生成以下輸出:

--Read-only cache entries cannot be updatedSELECT readonlyca0_.id AS id1_2_0_,readonlyca0_.NAME AS name2_2_0_ FROM repository readonlyca0_ WHERE readonlyca0_.id = 1 UPDATE repository SET NAME = 'High-Performance Hibernate' WHERE id = 1 --JdbcTransaction - rolled JDBC Connection--ERROR Expected --java.lang.UnsupportedOperationException: Can't write to a readonly object

因為只讀緩存實體實際上是不可變的,所以最好將它們賦予 Hibernate特有的@Immutable批注。

刪除實體

同時刪除關聯的實體時,也會刪除只讀緩存條目:

@Test public void testReadOnlyEntityDelete() {LOGGER.info("Read-only cache entries can be deleted");doInTransaction(session -> {Repository repository = (Repository) session.get(Repository.class, 1L);assertNotNull(repository);session.delete(repository);});doInTransaction(session -> {Repository repository = (Repository) session.get(Repository.class, 1L);assertNull(repository);}); }

生成以下輸出:

--Read-only cache entries can be deletedSELECT readonlyca0_.id AS id1_2_0_,readonlyca0_.NAME AS name2_2_0_ FROM repository readonlyca0_ WHERE readonlyca0_.id = 1;DELETE FROM repository WHERE id = 1--JdbcTransaction - committed JDBC ConnectionSELECT readonlyca0_.id AS id1_2_0_,readonlyca0_.NAME AS name2_2_0_ FROM repository readonlyca0_ WHERE readonlyca0_.id = 1; --JdbcTransaction - committed JDBC Connection

PersistenceContext使移除 實體狀態轉換入隊,并且在刷新時 ,數據庫和二級緩存都將刪除關聯的實體記錄。

集合緩存

提交實體具有變更組件的集合。

@ElementCollection @CollectionTable(name="commit_change",joinColumns=@JoinColumn(name="commit_id") ) private List<Change> changes = new ArrayList<>();

盡管Commit實體作為只讀元素進行緩存,但第二級緩存將忽略Change集合。

@Test public void testCollectionCache() {LOGGER.info("Collections require separate caching");doInTransaction(session -> {Repository repository = (Repository) session.get(Repository.class, 1L);Commit commit = new Commit(repository);commit.getChanges().add(new Change("README.txt", "0a1,5..."));commit.getChanges().add(new Change("web.xml", "17c17..."));session.persist(commit);});doInTransaction(session -> {LOGGER.info("Load Commit from database");Commit commit = (Commit) session.get(Commit.class, 1L);assertEquals(2, commit.getChanges().size());});doInTransaction(session -> {LOGGER.info("Load Commit from cache");Commit commit = (Commit) session.get(Commit.class, 1L);assertEquals(2, commit.getChanges().size());}); }

運行此測試將生成以下輸出:

--Collections require separate cachingSELECT readonlyca0_.id AS id1_2_0_,readonlyca0_.NAME AS name2_2_0_ FROM repository readonlyca0_ WHERE readonlyca0_.id = 1;INSERT INTO commit(id, repository_id) VALUES (DEFAULT, 1);INSERT INTO commit_change(commit_id, diff, path) VALUES (1, '0a1,5...', 'README.txt'); INSERT INTO commit_change(commit_id, diff, path) VALUES (1, '17c17...', 'web.xml');--JdbcTransaction - committed JDBC Connection--Load Commit from databaseSELECT readonlyca0_.id AS id1_2_0_,readonlyca0_.NAME AS name2_2_0_ FROM repository readonlyca0_ WHERE readonlyca0_.id = 1;SELECT changes0_.commit_id AS commit_i1_0_0_,changes0_.diff AS diff2_1_0_,changes0_.path AS path3_1_0_ FROM commit_change changes0_ WHERE changes0_.commit_id = 1 --JdbcTransaction - committed JDBC Connection--Load Commit from cacheSELECT changes0_.commit_id AS commit_i1_0_0_,changes0_.diff AS diff2_1_0_,changes0_.path AS path3_1_0_ FROM commit_change changes0_ WHERE changes0_.commit_id = 1 --JdbcTransaction - committed JDBC Connection

盡管Commit實體是從緩存中檢索的,但Change集合始終是從數據庫中獲取的。 由于更改也是不可變的,因此我們也希望對其進行緩存,以節省不必要的數據庫往返次數。

啟用集合緩存支持

默認情況下,不緩存集合,并且要啟用此行為,我們必須使用緩存并發策略為它們添加注釋:

@ElementCollection @CollectionTable(name="commit_change",joinColumns=@JoinColumn(name="commit_id") ) @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY ) private List<Change> changes = new ArrayList<>();

重新運行先前的測試將產生以下輸出:

--Collections require separate cachingSELECT readonlyca0_.id AS id1_2_0_,readonlyca0_.NAME AS name2_2_0_ FROM repository readonlyca0_ WHERE readonlyca0_.id = 1;INSERT INTO commit(id, repository_id) VALUES (DEFAULT, 1);INSERT INTO commit_change(commit_id, diff, path) VALUES (1, '0a1,5...', 'README.txt'); INSERT INTO commit_change(commit_id, diff, path) VALUES (1, '17c17...', 'web.xml');--JdbcTransaction - committed JDBC Connection--Load Commit from databaseSELECT readonlyca0_.id AS id1_2_0_,readonlyca0_.NAME AS name2_2_0_ FROM repository readonlyca0_ WHERE readonlyca0_.id = 1;SELECT changes0_.commit_id AS commit_i1_0_0_,changes0_.diff AS diff2_1_0_,changes0_.path AS path3_1_0_ FROM commit_change changes0_ WHERE changes0_.commit_id = 1 --JdbcTransaction - committed JDBC Connection--Load Commit from cache--JdbcTransaction - committed JDBC Connection

一旦集合被緩存,我們就可以獲取Commit實體及其所有Change,而無需訪問數據庫。

結論

只讀實體可以安全地進行緩存,我們可以僅使用第二級緩存來加載整個不可變實體圖。 由于高速緩存是直通的 ,因此從數據庫中獲取實體時將對其進行高速緩存。 只讀緩存不是直寫的,因為持久存儲實體只會在新的數據庫行中實現,而不會傳播到緩存中。

  • 代碼可在GitHub上獲得 。

翻譯自: https://www.javacodegeeks.com/2015/04/how-does-hibernate-read_only-cacheconcurrencystrategy-work.html

總結

以上是生活随笔為你收集整理的Hibernate READ_ONLY CacheConcurrencyStrategy如何工作的全部內容,希望文章能夠幫你解決所遇到的問題。

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