2016-05-20 3 views
0

У меня есть служба, которая вызывает внешнюю систему для извлечения каких-либо объектов по их внешнему идентификатору, а также для отправки их обратно для обновления. Вместо извлечения объектов по одному есть более общие методы назначения:Spring cache/jsr107: аргумент list/collection как часть ключа

public interface ExternalSystem { 
    List<ExternalDTO> getObjects(List<String> externalIds); 

    void updateObjects(List<ExternalDTO> updates); 
} 

Я хотел бы поставить кэш на вершине ExternalSystem звонков, потому что они являются весьма дорогостоящими.

В реализации службы я могу просто поставить пружинные аннотации:

@Cacheable("cache-external") 
List<ExternalDTO> getObjects(List<String> externalIds) {} 

@CacheEvict(cacheNames="cache-external", allEntries=true) 
void updateObjects(List<ExternalDTO> updates); 

Однако такой кэш будет вести себя очень плохо в случае, если у меня есть много пересечения между externalIds, т.е.

  1. Вызов # 1 getObjects ([1,2,3,4]) -> кэш, помещенный клавишей [1,2,3,4]
  2. Звоните # 2 getObjects ([1,2,3,4,5]) -> кэш, помещенный ключом [1,2,3,4,5]
  3. Звоните # 3 г etObjects ([6,7,8,9]) -> кэш, помещаемый ключом [6,7,8,9]
  4. Вызов # 4 updateObjects (1) -> выселение всех кешей, но третий кеш не содержат 3

Итак, вопрос заключается в том, как реализовать пользовательскую стратегию (я предполагаю, что это не выполнимо из коробки), которая вытеснит только те записи, которые действительно должны быть выселены, и сделает ключи такими способами что пересекающиеся объекты извлекаются из кеша?

Обновление. Я нашел два одинаковых вопроса:

  1. spring-cache-abstraction-with-multi-value-queries
  2. using-spring-cache-on-methods-that-take-an-array-or-collection
  3. spring-cacheable-methods-with-lists

UPD2. Вот что-то похожее на то, что я хочу, кроме того, что я положу в пары кэша String и ExternalDTO для каждого элемента в коллекции. element-level-caching-of-list-to-list

ответ

0

AFAIK это невозможно с аннотациями. Вы можете использовать императивный API, который содержит необходимые вам объемные операции, например Cache.getAll(keySet) и Cache.removeAll(keySet)

+0

Да, и я уверен, что уже должны быть некоторые пользовательские реализации. Речь идет не только об изъятиях, см. Прилагаемые вопросы в «Обновлении». –

+1

Просто любопытно: Сколько экземпляров ваше приложение обычно запрашивает сразу? Если вы не можете сделать это через массовый запрос, а один за другим, вы не сможете удовлетворить максимальные требования к задержке со своего клиента? Если вы пойдете на собственное решение: вы профилировали все свое приложение, и это оптимизация, которая будет иметь наибольшее влияние? Просто спрашиваю;) – cruftex

+0

Это хороший вопрос, но даже если это выполнимо в моем случае, это может быть невыполнимо в других случаях. Итак, вопрос более общий, чем мой случай. Итак, я ищу какое-то многоразовое решение для таких случаев. Если я его не найду, я напишу свое и опубликую здесь :) –

Смежные вопросы