2011-09-15 53 views
9

我目前正在滾動我自己的小ORM,並發現自己面臨創建規範化映射的任務,以防止從數據庫中多次加載相同的實體。如何在Java中實現規範化映射?

我目前的做法是使用HashMap<Object, WeakReference<Object>>。密鑰是映射數據庫實體的主鍵(如果它是組合鍵,則爲ArrayList<Object>),值爲WeakReference<Object>

我的主要問題是如何清理地圖?當一個對象不再被使用時,地圖中的弱引用將會變爲null,我只會在下一次查找時發現它(或者從不,如果我不再查看該對象)。我可以通過ReferenceQueue清除弱引用寄存器,然後在每次查找時檢查該隊列。清除的引用不會給我任何關於哪個對象被清除的提示,所以我想我必須繼承WeakReference以將鍵存儲在映射中,所以我可以在清除引用後將其刪除。

這是要走的路,還是有任何簡單的方法來實現呢?

回答

13

我會推薦在r10中使用番石榴的MapMakerCacheBuilder

他們允許自動*基於時間和大小的驅逐,以及支持弱密鑰或值。 (即將CacheBuilder承諾,專門針對這種使用情況。)

所以,你可以初始化地圖:

ConcurrentMap<Key, Object> cache = new MapMaker() 
     .weakValues() 
     .makeMap(); 

而直接的好處將是當垃圾回收的值時,整個條目將被刪除。此外,您還可以使用計算映射:

ConcurrentMap<Key, Object> cache = new MapMaker() 
     .weakValues() 
     .makeComputingMap(loadFunction); 

其中loadFunction是從數據庫加載對象的Function<Key, Object>。這樣做的好處是該映射將處理對特定對象的併發請求,從而確保該查詢只被調用一次。此外,請求代碼只需要調用get(),並且始終可以期待對象返回,無論是來自緩存還是數據庫。

這些例子使用MapMaker - 我還沒有玩過CacheBuilder的樂趣呢。

查看我的問題my ideal cache using guava瞭解更多示例。這篇文章討論瞭如何將基於時間的驅逐與規範化相結合。

+2

我一開始很猶豫是否要添加這個庫,但現在我已經這麼做了,我想知道爲什麼我沒有這麼做。感謝這個偉大的答案! –