hibernate查询缓存_Hibernate查询缓存如何工作
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。
本機查詢無效
正如我前面提到 ,本機查詢Hibernate留在黑暗中,因為它可以不知道本地查詢最終可能會修改其表。 在以下測試中,我們將更新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查詢緩存
總結
以上是生活随笔為你收集整理的hibernate查询缓存_Hibernate查询缓存如何工作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电脑版邮箱客户端下载(电脑版邮箱客户端下
- 下一篇: 手机成为肉鸡怎么办(手机怎么当肉鸡ddo