Как реализовать канонизирующее отображение в Java?
В настоящее время я запускаю свой собственный маленький ORM и сталкиваюсь с задачей создания канонизирующего отображения, чтобы предотвратить загрузку одного и того же объекта из базы данных более одного раза.
Мой текущий подход заключается в использовании HashMap<Object, WeakReference<Object>>
, Ключ является первичным ключом сопоставленного объекта базы данных (ArrayList<Object>
если это составной ключ), а значения WeakReference<Object>
,
Моя главная проблема - как почистить карту? Когда объект больше не используется, слабая ссылка на карте уйдет null
, и я обнаружу это только при следующем поиске (или никогда, если я не посмотрю объект снова). Я мог бы сделать регистр слабых ссылок с ReferenceQueue
когда они очищаются, а затем проверяют эту очередь каждый раз, когда я что-то ищу. Очищенная ссылка не дала бы мне никакого намека на то, какой объект был очищен, поэтому, я думаю, мне придется подкласс WeakReference
сохранить ключ на карте, чтобы я мог удалить его после очистки ссылки.
Это путь, или есть какой-то более простой способ реализовать это?
1 ответ
Я бы порекомендовал использовать 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
еще.
Смотрите мой вопрос мой идеальный кеш с использованием гуавы для большего количества примеров. В этом посте обсуждается, как объединить основанное на времени выселение с канонизацией.