有幾種選擇,當然,但像往常一樣,春天有你的回。
最簡單,最簡單的方法是利用Spring的@Caching
註解您save
方法,像這樣......
@Caching(evict = {
@CacheEvict(cacheNames = "Users", key="#user.name"),
@CacheEvict(cacheNames = "Users", key="#user.email")
})
User save(User user);
供您參考,我創建了一個例子測試類演示該工作here。
你會發現我模仿你的例子使用Spring的我的UserRepository緩存抽象註釋。在這種情況下,我的回購支持Pivotal GemFire,但任何數據存儲都可以使用。我使用ConcurrentMap
作爲我的緩存提供者,使用Spring的ConcurrentMapCacheManager,但當然,任何緩存提供者都會這樣做。
我的test case繼續保存新的User
,確保用戶存儲尚未緩存。然後測試繼續執行查詢方法(findByName
,findByEmail
),確保在每種情況下都適當地緩存用戶實體。然後,我從底層數據存儲中刪除實體,並確保實體仍然被緩存。最後,在真實時刻,我修改實體,重新保存實體,聲稱實體存儲在那個全部條目已經從緩存中「驅逐」。
您也可以嘗試,爲其他的優化,到@CachePut
註釋在這種情況下,2個@CacheEvict
註釋結合,這可能基於新的,更新的實體,類似於恢復緩存...
@Caching(
evict = {
@CacheEvict(cacheNames = "Users", key="#a0.name", beforeInvocation = true),
@CacheEvict(cacheNames = "Users", key="#a0.email", beforeInvocation = true)
},
put = {
@CachePut(cacheNames = "Users", key="#result.name"),
@CachePut(cacheNames = "Users", key="#result.email")
}
)
User save(User user);
注意:請注意在@CacheEvict
註解beforeInvocation
屬性與@CachePuts
然而沿着用戶,你可能更喜歡實體懶洋洋地加入到基於需求的高速緩存。
雖然您會假定實體正在被頻繁訪問/使用,因爲剛剛調用了您的倉庫中的save
方法,因此需要依賴底層數據存儲(如GemFire)來設置額外的驅逐(基於溢出) /到期(基於LRU)設置,從而更好地管理系統資源(例如內存),同時仍保持最佳的應用程序性能。
思考的食物。
希望這會有所幫助。
謝謝,這看起來不錯。問題:#a0,#a1,...和#p0,p1,...之間有什麼區別,以及使用方法參數var name'user'。(其實,我似乎無法得到參數名稱在SpEL中工作,我得到一個錯誤:「屬性字段用戶名無法找到null」,null是對象)。 – Saul
另一個想法是:儘管使用#result.name和result.email預先填充緩存似乎有意義,但我擔心使用beforeInvocation = true的併發問題。簡單地使用@CachePut(key =「#a0.name」)等可能更安全,即save()實現的影響和可能性實際上改變了值與併發問題的影響和可能性。 – Saul
另一個問題是:在上面的例子中,email屬性可能不是null。這對某些緩存實現(例如concurrentHashMap)不起作用。我希望有一個名爲'ignoreNullKeys'的參數,我可以將其設置爲false,而該參數不會對具有空值的鍵執行'doEvict'或'put'調用。 – Saul