2011-09-15 10 views
9

私は現在、自分の小さなORMを動かしています。データベースから同じエンティティを複数回ロードするのを防ぐために、正規化マッピングを作成する作業に直面しています。Javaで正規化マッピングを実装する方法は?

私の現在のアプローチはHashMap<Object, WeakReference<Object>>です。キーは、マップされたデータベースエンティティ(複合キーの場合はArrayList<Object>)の主キーで、値はWeakReference<Object>です。

私の主な問題は、マップをクリーンアップする方法ですか?オブジェクトがもう使用されなくなると、マップ内の弱い参照はnullになります。次回のルックアップでしか見つからないでしょう。彼らがクリアされたら弱い参照をReferenceQueueに登録させてから、何か調べるたびにそのキューをチェックすることができます。クリアされた参照は、どのオブジェクトがクリアされたかについて私には何のヒントも与えていないので、マップにキーを格納するためにサブクラスWeakReferenceを持っていなければならないと思います。

これは方法ですか、これを実装する簡単な方法がありますか?

答えて

13

GuavaのMapMaker、またはr10のCacheBuilderを使用することをおすすめします。

これらは、自動的に*の時間とサイズに基づいた削除と弱いキーや値のサポートを可能にします。 (今後のCacheBuilder約束は、特別に使用例このように合わせて調整することにする。)

はつまり、あなたのマップを初期化することができます

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

を、すぐに利益になります、その値がガベージコレクトされたときに、エントリ全体が削除されます。 loadFunctionは、データベースからオブジェクトをロードFunction<Key, Object>ある

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

:さらに、あなたは、コンピューティング・マップを使用することができます。これの利点は、マップが特定のオブジェクトに対する同時リクエストを処理し、クエリが一度だけ呼び出されることを保証することです。さらに、要求コードはget()だけを呼び出す必要があり、キャッシュまたはデータベースのいずれの場合でもオブジェクトをいつも戻すことができます。

これらの例では、MapMakerを使用しています - 私はCacheBuilderでおもちゃに喜んでいませんでした。

詳細については、my ideal cache using guavaをご覧ください。その記事では、時間ベースの追放を正式化と組み合わせる方法について議論しています。

+2

私は最初にこのライブラリを追加することを躊躇しましたが、今は私がしたので、なぜ私はそれを早くやっていないのだろうかと思います。この素晴らしい答えをありがとう! –

関連する問題