Как реализовать канонизирующее отображение в Java? - PullRequest
10 голосов
/ 15 сентября 2011

В настоящее время я запускаю свой собственный маленький ORM и сталкиваюсь с задачей создания канонизирующего отображения, чтобы предотвратить загрузку одного и того же объекта из базы данных более одного раза.

Мой текущий подход заключается виспользуйте HashMap<Object, WeakReference<Object>>.Ключ является первичным ключом сопоставленной сущности базы данных (ArrayList<Object>, если это составной ключ), а значения равны WeakReference<Object>.

Моя главная проблема заключается в том, как очистить карту?Когда объект больше не используется, слабая ссылка на карте будет иметь значение null, и я обнаружу это только при следующем поиске (или никогда, если я не посмотрю объект снова).Я мог бы зарегистрировать слабые ссылки со значением ReferenceQueue, когда они будут очищены, и затем проверять эту очередь каждый раз, когда я что-то просматриваю.Очищенная ссылка не дает мне никаких подсказок относительно того, какой объект был очищен, поэтому, я думаю, мне нужно было бы создать подкласс WeakReference, чтобы сохранить ключ на карте, поэтому я могу удалить его после очистки ссылки.

Это путь или есть какой-то более простой способ реализовать это?

1 Ответ

14 голосов
/ 16 сентября 2011

Я бы рекомендовал использовать MapMaker от Guava или CacheBuilder в r10.

Они допускают автоматическое * выселение по времени и размеру, а также поддерживают слабые ключи или значения. (Предстоящий 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.

См. Мой вопрос Мой идеальный кеш, использующий guava , для большего количества примеров. В этом посте обсуждается, как объединить основанное на времени выселение с канонизацией.

...