12

私は現在、自分の小さな ORM を展開していますが、データベースから同じエンティティを複数回ロードするのを防ぐために、正規化マッピングを作成するタスクに直面していることに気付きました。

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

私の主な問題は、マップをクリーンアップする方法ですか? オブジェクトが使用されなくなると、マップ内の弱い参照が移動nullし、次のルックアップでのみこれを発見します (または、オブジェクトを再度ルックアップしない場合は決して発見しません)。弱い参照ReferenceQueueがクリアされたときに に登録し、何かを調べるたびにそのキューをチェックすることができます。WeakReferenceただし、参照がクリアされても、どのオブジェクトがクリアされたかについてのヒントは得られないため、キーをマップに格納するためにサブクラス化する必要があると思われるため、参照がクリアされた後に削除できます。

これは進むべき道ですか、それともこれを実装する簡単な方法はありますか?

4

1 に答える 1

16

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

*時間ベースおよびサイズベースの自動エビクションが可能で、弱いキーまたは値をサポートします。(今後のCacheBuilder約束は、この種のユースケースに合わせて特別に調整されます。)

したがって、マップを初期化できます。

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

そしてすぐに得られる利点は、値がガベージ コレクションされると、エントリ全体が削除されることです。さらに、計算マップを使用できます。

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

loadFunctionFunction<Key, Object>データベースからオブジェクトをロードする です。これの利点は、マップが特定のオブジェクトに対する同時要求を処理し、クエリが 1 回だけ呼び出されるようにすることです。さらに、要求側のコードは呼び出しのみを必要get()とし、キャッシュまたはデータベースのいずれからでもオブジェクトが返されることを常に期待できます。

これらの例は使用しMapMakerています-私はまだいじる喜びがありCacheBuilderませんでした.

他の例については、グアバを使用した私の理想的なキャッシュの質問を参照してください。その投稿では、時間ベースのエビクションと正規化を組み合わせる方法について説明しています。

于 2011-09-15T20:01:28.417 に答える