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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Hibernate查询缓存如何工作

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

介紹

既然我已經介紹了實體和集合緩存,現在該研究查詢緩存的工作原理了。

查詢緩存與實體嚴格相關,它在搜索條件和滿足該特定查詢過濾器的實體之間繪制關聯。 像其他Hibernate功能一樣,查詢緩存也不像人們想象的那么瑣碎。

實體模型

對于我們的測試用例,我們將使用以下域模型:

Post實體與Author 具有多對一關聯,并且兩個實體都存儲在第二級緩存中。

啟用查詢緩存

默認情況下,查詢緩存處于禁用狀態,要激活它,我們需要提供以下Hibernate屬性:

properties.put("hibernate.cache.use_query_cache", Boolean.TRUE.toString());

為了使Hibernate緩存給定的查詢結果,我們需要在創建Query時顯式設置cachable查詢屬性 。

直讀緩存

查詢緩存是只讀的 ,就像NONSTRICT_READ_WRITE并發策略一樣 ,它只能使陳舊的條目無效。

在下一個示例中,我們將緩存以下查詢:

private List<Post> getLatestPosts(Session session) {return (List<Post>) session.createQuery("select p " +"from Post p " +"order by p.createdOn desc").setMaxResults(10).setCacheable(true).list(); }

首先,我們將使用以下測試案例來研究查詢緩存的內部結構:

doInTransaction(session -> {LOGGER.info("Evict regions and run query");session.getSessionFactory().getCache().evictAllRegions();assertEquals(1, getLatestPosts(session).size()); });doInTransaction(session -> {LOGGER.info("Check get entity is cached");Post post = (Post) session.get(Post.class, 1L); });doInTransaction(session -> {LOGGER.info("Check query result is cached");assertEquals(1, getLatestPosts(session).size()); });

該測試生成以下輸出:

QueryCacheTest - Evict regions and run queryStandardQueryCache - Checking cached query results in region: org.hibernate.cache.internal.StandardQueryCache EhcacheGeneralDataRegion - Element for key sql: selectquerycache0_.id as id1_1_,querycache0_.author_id as author_i4_1_,querycache0_.created_on as created_2_1_,querycache0_.name as name3_1_ fromPost querycache0_ order byquerycache0_.created_on desc;parameters: ; named parameters: {}; max rows: 10; transformer: org.hibernate.transform.CacheableResultTransformer@110f2 is null StandardQueryCache - Query results were not found in cacheselectquerycache0_.id as id1_1_,querycache0_.author_id as author_i4_1_,querycache0_.created_on as created_2_1_,querycache0_.name as name3_1_ fromPost querycache0_ order byquerycache0_.created_on desc limit 10StandardQueryCache - Caching query results in region: org.hibernate.cache.internal.StandardQueryCache; timestamp=5872026465492992 EhcacheGeneralDataRegion - key: sql: selectquerycache0_.id as id1_1_,querycache0_.author_id as author_i4_1_,querycache0_.created_on as created_2_1_,querycache0_.name as name3_1_ fromPost querycache0_ order byquerycache0_.created_on desc;parameters: ; named parameters: {}; max rows: 10; transformer: org.hibernate.transform.CacheableResultTransformer@110f2 value: [5872026465492992, 1]JdbcTransaction - committed JDBC Connection------------------------------------------------------------QueryCacheTest - Check get entity is cachedJdbcTransaction - committed JDBC Connection------------------------------------------------------------QueryCacheTest - Check query is cachedStandardQueryCache - Checking cached query results in region: org.hibernate.cache.internal.StandardQueryCache StandardQueryCache - Checking query spaces are up-to-date: [Post]EhcacheGeneralDataRegion - key: Post UpdateTimestampsCache - [Post] last update timestamp: 5872026465406976, result set timestamp: 5872026465492992 StandardQueryCache - Returning cached query resultsJdbcTransaction - committed JDBC Connection
  • 清除所有緩存區域,以確保緩存為空
  • 運行后查詢后,查詢緩存將檢查以前存儲的結果
  • 因為沒有緩存條目,所以查詢轉到數據庫
  • 所選實體和查詢結果均被緩存
  • 然后,我們驗證Post實體是否存儲在二級緩存中
  • 后續查詢請求將從緩存中解決,而無需訪問數據庫

查詢參數

查詢參數嵌入在緩存條目鍵中,如以下示例所示。

基本類型

首先,我們將使用基本的類型過濾:

private List<Post> getLatestPostsByAuthorId(Session session) {return (List<Post>) session.createQuery("select p " +"from Post p " +"join p.author a " +"where a.id = :authorId " +"order by p.createdOn desc").setParameter("authorId", 1L).setMaxResults(10).setCacheable(true).list(); }doInTransaction(session -> {LOGGER.info("Query cache with basic type parameter");List<Post> posts = getLatestPostsByAuthorId(session);assertEquals(1, posts.size()); });

查詢緩存條目如下所示:

EhcacheGeneralDataRegion - key: sql: selectquerycache0_.id as id1_1_,querycache0_.author_id as author_i4_1_,querycache0_.created_on as created_2_1_,querycache0_.name as name3_1_ fromPost querycache0_ inner joinAuthor querycache1_ on querycache0_.author_id=querycache1_.id wherequerycache1_.id=? order byquerycache0_.created_on desc;parameters: ; named parameters: {authorId=1}; max rows: 10; transformer: org.hibernate.transform.CacheableResultTransformer@110f2 value: [5871781092679680, 1]

該參數存儲在高速緩存條目鍵中。 緩存條目值的第一個元素始終是結果集的獲取時間戳。 以下元素是此查詢返回的實體標識符。

實體類型

我們還可以使用實體類型作為查詢參數:

private List<Post> getLatestPostsByAuthor(Session session) {Author author = (Author) session.get(Author.class, 1L);return (List<Post>) session.createQuery("select p " +"from Post p " +"join p.author a " +"where a = :author " +"order by p.createdOn desc").setParameter("author", author).setMaxResults(10).setCacheable(true).list(); }doInTransaction(session -> {LOGGER.info("Query cache with entity type parameter");List<Post> posts = getLatestPostsByAuthor(session);assertEquals(1, posts.size()); });

緩存條目與我們之前的示例相似,因為Hibernate僅將實體標識符存儲在緩存條目鍵中。 這很有意義,因為Hibernate已經緩存了Author實體。

EhcacheGeneralDataRegion - key: sql: selectquerycache0_.id as id1_1_,querycache0_.author_id as author_i4_1_,querycache0_.created_on as created_2_1_,querycache0_.name as name3_1_ fromPost querycache0_ inner joinAuthor querycache1_ on querycache0_.author_id=querycache1_.id wherequerycache1_.id=? order byquerycache0_.created_on desc;parameters: ; named parameters: {author=1}; max rows: 10; transformer: org.hibernate.transform.CacheableResultTransformer@110f2 value: [5871781092777984, 1]

一致性

HQL / JPQL查詢無效

Hibernate二級緩存偏向于強一致性,而查詢緩存也不例外。 與刷新一樣,只要關聯的表空間發生更改,查詢緩存就可以使其條目無效。 每次我們持久/刪除/更新實體時 ,使用該特定表的所有查詢緩存條目都將失效。

doInTransaction(session -> {Author author = (Author) session.get(Author.class, 1L);assertEquals(1, getLatestPosts(session).size());LOGGER.info("Insert a new Post");Post newPost = new Post("Hibernate Book", author);session.persist(newPost);session.flush();LOGGER.info("Query cache is invalidated");assertEquals(2, getLatestPosts(session).size()); });doInTransaction(session -> {LOGGER.info("Check Query cache");assertEquals(2, getLatestPosts(session).size()); });

該測試將添加一個新的Post ,然后重新運行可緩存的查詢。 運行此測試將給出以下輸出:

QueryCacheTest - Insert a new Postinsert intoPost(id, author_id, created_on, name) values(default, 1, '2015-06-06 17:29:59.909', 'Hibernate Book')UpdateTimestampsCache - Pre-invalidating space [Post], timestamp: 5872029941395456 EhcacheGeneralDataRegion - key: Post value: 5872029941395456QueryCacheTest - Query cache is invalidated StandardQueryCache - Checking cached query results in region: org.hibernate.cache.internal.StandardQueryCache EhcacheGeneralDataRegion - key: sql: selectquerycache0_.id as id1_1_,querycache0_.author_id as author_i4_1_,querycache0_.created_on as created_2_1_,querycache0_.name as name3_1_ fromPost querycache0_ order byquerycache0_.created_on desc;parameters: ; named parameters: {}; max rows: 10; transformer: org.hibernate.transform.CacheableResultTransformer@110f2StandardQueryCache - Checking query spaces are up-to-date: [Post] EhcacheGeneralDataRegion - key: Post UpdateTimestampsCache - [Post] last update timestamp: 5872029941395456, result set timestamp: 5872029695619072 StandardQueryCache - Cached query results were not up-to-dateselectquerycache0_.id as id1_1_,querycache0_.author_id as author_i4_1_,querycache0_.created_on as created_2_1_,querycache0_.name as name3_1_ fromPost querycache0_ order byquerycache0_.created_on desc limit 10StandardQueryCache - Caching query results in region: org.hibernate.cache.internal.StandardQueryCache; timestamp=5872029695668224 EhcacheGeneralDataRegion - key: sql: selectquerycache0_.id as id1_1_,querycache0_.author_id as author_i4_1_,querycache0_.created_on as created_2_1_,querycache0_.name as name3_1_ fromPost querycache0_ order byquerycache0_.created_on desc;parameters: ; named parameters: {}; max rows: 10; transformer: org.hibernate.transform.CacheableResultTransformer@110f2 value: [5872029695668224, 2, 1]JdbcTransaction - committed JDBC ConnectionUpdateTimestampsCache - Invalidating space [Post], timestamp: 5872029695680512 EhcacheGeneralDataRegion - key: Post value: 5872029695680512------------------------------------------------------------QueryCacheTest - Check Query cacheStandardQueryCache - Checking cached query results in region: org.hibernate.cache.internal.StandardQueryCache EhcacheGeneralDataRegion - key: sql: selectquerycache0_.id as id1_1_,querycache0_.author_id as author_i4_1_,querycache0_.created_on as created_2_1_,querycache0_.name as name3_1_ fromPost querycache0_ order byquerycache0_.created_on desc;parameters: ; named parameters: {}; max rows: 10; transformer: org.hibernate.transform.CacheableResultTransformer@110f2StandardQueryCache - Checking query spaces are up-to-date: [Post] EhcacheGeneralDataRegion - key: Post UpdateTimestampsCache - [Post] last update timestamp: 5872029695680512, result set timestamp: 5872029695668224 StandardQueryCache - Cached query results were not up-to-dateselectquerycache0_.id as id1_1_,querycache0_.author_id as author_i4_1_,querycache0_.created_on as created_2_1_,querycache0_.name as name3_1_ fromPost querycache0_ order byquerycache0_.created_on desc limit 10StandardQueryCache - Caching query results in region: org.hibernate.cache.internal.StandardQueryCache; timestamp=5872029695705088 EhcacheGeneralDataRegion - key: sql: selectquerycache0_.id as id1_1_,querycache0_.author_id as author_i4_1_,querycache0_.created_on as created_2_1_,querycache0_.name as name3_1_ fromPost querycache0_ order byquerycache0_.created_on desc;parameters: ; named parameters: {}; max rows: 10; transformer: org.hibernate.transform.CacheableResultTransformer@110f2 value: [5872029695705088, 2, 1]JdbcTransaction - committed JDBC Connection
  • 一旦Hibernate檢測到Entity狀態轉換 ,它將使受影響的查詢緩存區域預先失效
  • 不會刪除查詢緩存條目,但會更新其關聯的時間戳
  • 查詢緩存始終檢查條目鍵時間戳,如果鍵時間戳比結果集加載時間戳新,它將跳過讀取其值。
  • 如果當前會話重新運行此查詢,則結果將再次被緩存
  • 當前數據庫事務的提交和更改從會話級隔離傳播到常規讀取一致性
  • 發生實際的無效,并且緩存條目時間戳再次更新

這種方法可能會破壞READ COMMITTED一致性保證,因為可能進行臟讀 ,因為在提交數據庫事務之前,當前隔離的更改會傳播到Cache。

本機查詢無效

正如我前面提到 ,本機查詢休眠留在黑暗中,因為它可以不知道本地查詢最終可能會修改其表。 在以下測試中,我們將更新Author表,同時檢查它對當前Post Query Cache的影響:

doInTransaction(session -> {assertEquals(1, getLatestPosts(session).size());LOGGER.info("Execute native query");assertEquals(1, session.createSQLQuery("update Author set name = '\"'||name||'\"' ").executeUpdate());LOGGER.info("Check query cache is invalidated");assertEquals(1, getLatestPosts(session).size()); });

測試生成以下輸出:

QueryCacheTest - Execute native queryUpdateTimestampsCache - Pre-invalidating space [Author], timestamp: 5872035446091776 EhcacheGeneralDataRegion - key: Author value: 5872035446091776 UpdateTimestampsCache - Pre-invalidating space [Post], timestamp: 5872035446091776 EhcacheGeneralDataRegion - key: Post value: 5872035446091776updateAuthor setname = '"'||name||'"'QueryCacheTest - Check query cache is invalidatedStandardQueryCache - Checking cached query results in region: org.hibernate.cache.internal.StandardQueryCache EhcacheGeneralDataRegion - key: sql: selectquerycache0_.id as id1_1_,querycache0_.author_id as author_i4_1_,querycache0_.created_on as created_2_1_,querycache0_.name as name3_1_ fromPost querycache0_ order byquerycache0_.created_on desc;parameters: ; named parameters: {}; max rows: 10; transformer: org.hibernate.transform.CacheableResultTransformer@110f2StandardQueryCache - Checking query spaces are up-to-date: [Post] EhcacheGeneralDataRegion - key: Post UpdateTimestampsCache - [Post] last update timestamp: 5872035446091776, result set timestamp: 5872035200290816 StandardQueryCache - Cached query results were not up-to-dateselectquerycache0_.id as id1_1_,querycache0_.author_id as author_i4_1_,querycache0_.created_on as created_2_1_,querycache0_.name as name3_1_ fromPost querycache0_ order byquerycache0_.created_on desc limit 10StandardQueryCache - Caching query results in region: org.hibernate.cache.internal.StandardQueryCache; timestamp=5872035200364544 EhcacheGeneralDataRegion - key: sql: selectquerycache0_.id as id1_1_,querycache0_.author_id as author_i4_1_,querycache0_.created_on as created_2_1_,querycache0_.name as name3_1_ fromPost querycache0_ order byquerycache0_.created_on desc;parameters: ; named parameters: {}; max rows: 10; transformer: org.hibernate.transform.CacheableResultTransformer@110f2 value: [5872035200364544, 1]JdbcTransaction - committed JDBC ConnectionUpdateTimestampsCache - Invalidating space [Post], timestamp: 5872035200372736 EhcacheGeneralDataRegion - key: Post value: 5872035200372736 UpdateTimestampsCache - Invalidating space [Author], timestamp: 5872035200372736 EhcacheGeneralDataRegion - key: Author value: 5872035200372736

即使僅修改了Author表, Author和Post緩存區域也都無效。 為了解決這個問題,我們需要讓Hibernate知道我們要更改哪些表。

本機查詢緩存區域同步

Hibernate允許我們通過查詢同步提示來定義查詢表空間。 提供此信息時,Hibernate可使請求的緩存區域無效:

doInTransaction(session -> {assertEquals(1, getLatestPosts(session).size());LOGGER.info("Execute native query with synchronization");assertEquals(1, session.createSQLQuery("update Author set name = '\"'||name||'\"' ").addSynchronizedEntityClass(Author.class).executeUpdate());LOGGER.info("Check query cache is not invalidated");assertEquals(1, getLatestPosts(session).size()); });

正在生成以下輸出:

QueryCacheTest - Execute native query with synchronizationUpdateTimestampsCache - Pre-invalidating space [Author], timestamp: 5872036893995008 EhcacheGeneralDataRegion - key: Author value: 5872036893995008updateAuthor setname = '"'||name||'"'QueryCacheTest - Check query cache is not invalidatedStandardQueryCache - Checking cached query results in region: org.hibernate.cache.internal.StandardQueryCache EhcacheGeneralDataRegion - key: sql: selectquerycache0_.id as id1_1_,querycache0_.author_id as author_i4_1_,querycache0_.created_on as created_2_1_,querycache0_.name as name3_1_ fromPost querycache0_ order byquerycache0_.created_on desc;parameters: ; named parameters: {}; max rows: 10; transformer: org.hibernate.transform.CacheableResultTransformer@110f2StandardQueryCache - Checking query spaces are up-to-date: [Post] EhcacheGeneralDataRegion - key: Post UpdateTimestampsCache - [Post] last update timestamp: 5872036648169472, result set timestamp: 5872036648226816 StandardQueryCache - Returning cached query resultsJdbcTransaction - committed JDBC ConnectionUpdateTimestampsCache - Invalidating space [Author], timestamp: 5872036648263680 EhcacheGeneralDataRegion - key: Author value: 5872036648263680

只有提供的表空間無效,離開了郵政查詢緩存不變。 可以將本機查詢和查詢緩存混合在一起,但是需要一些努力。

結論

查詢緩存可以提高頻繁執行的實體查詢的應用程序性能,但這不是免費的。 它容易受到一致性問題的影響,并且如果沒有適當的內存管理控制機制,它很容易變得很大。

代碼可在GitHub上獲得 。

翻譯自: https://www.javacodegeeks.com/2015/06/how-does-hibernate-query-cache-work.html

總結

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

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