2014-03-04 107 views
0

我們需要緩存查詢的結果;該查詢返回數據庫的整個表。問題在於數據庫由其他應用程序在外部進行更改;執行查詢的Java應用程序會被更改的行的確切主鍵通知。從JPA/Hibernate/EclipseLink替換查詢緩存中的單個實體?

是否可以只從查詢緩存中替換已更改的元素,而不是整個列表? 這是第一級緩存(來自EntityManager)第二級緩存(來自EntityManagerFactory)還是不同的緩存?

如果這可以從JPA完成嗎?

entityManager.refersh(entity); 

,或者這是查詢緩存的二級高速緩存JPA:

entityManagerFactory.getCache().evict(cls, primaryKey); 

或只能通過Hibernate/API的EclipseLink?

如果不可能,爲了達到這個目的,會在所有元件上調用entityManager.find()嗎?

我還沒有在Hibernate documentationEclipseLink documentation中找到任何有用信息。 Hibernate支持區域和只刷新區域,但我們需要實體級刷新粒度。


後來編輯澄清我的發現。

繼評論中@Chris發佈的鏈接後,我發現我想要的實際上是supported by EclipseLink,但只適用於Oracle數據庫(可能爲其他供應商實現自己的處理程序;但數據庫的調用不是標準化的並且因供應商而異)。我還沒有找到,如果Hibernate支持這個或沒有。

無論如何,與Spring Cache(基於CocurrentMap)或基於定製的高速緩存相比,EclipseLink的查詢高速緩存性能有一些非常差的性能,因此Spring Cache或Spring Jdbc上的自定義高速緩存將保留。

回答

1

EntityManager.refresh()是你想要的 - 它刷新數據庫內容的實體。如果你不在事務中,這也應該更新共享緩存中的實體,否則你可能需要使用entityManagerFactory.getCache()。evict(cls,primaryKey);以及清除二級共享緩存,以便稍後可以讀取它。

+0

所以查詢緩存不是一個單獨的緩存? – m3th0dman

+1

查詢緩存不是JPA的一部分,因此您必須將其配置爲專用於您的提供者 - 默認情況下,EclipseLink的查詢緩存未打開,僅適用於查詢結果,而不適用於返回的數據。所以只要查詢返回相同的實體,就應該從數據庫中提取無效的實體。 – Chris

+1

對不起,意思是說文檔暗示無效實體應該從數據庫中刷新。如果更改影響將返回的查詢結果(ID,而不是原始實體數據值),則需要使查詢緩存無效。在EclipseLink 2.5中,這個變化使無效實體自動使用這些實體使查詢無效:http://java-persistence-performance.blogspot.com/2013/06/cool-performance-features-of.html – Chris