@Cacheable на методе с параметром типа List — ключ кэша считает не то
Код выглядит рабочим и проходит все ручные проверки в дев-окружении.
@Cacheable("orders") public List findByIds( List ids) { return repository.findAllById(ids); }
По умолчанию Spring строит ключ кэша через SimpleKeyGenerator, который вызывает hashCode() и equals() у аргумента. У ArrayList оба метода определены по содержимому и порядку элементов — значит вызов с [1, 2, 3] и [3, 2, 1] даст два разных ключа кэша, хотя набор заказов на выходе логически один и тот же для бизнеса.
Проблема не в самом кэше — он честно работает по контракту equals/hashCode. Проблема в том, что список как параметр несёт порядок, а бизнес-смысл запроса порядок не учитывает. Кэш раздувается дублирующими записями под разные перестановки одного и того же набора id.
Чинят это сортировкой списка перед вызовом метода или явным key через SpEL: @Cacheable(value = "orders", key = "#ids.stream().sorted().toList()"). Второй вариант ловушка — SpEL здесь тоже строит ключ через toString() или hashCode() промежуточного объекта, и если забыть toList() в конце цепочки, ключом станет hashCode самого Stream — он разный при каждом вызове.
Кэш по коллекции без нормализации порядка — тихий рост memory footprint без единой ошибки в логах.
Тренажёр: 600 вопросов, мок с таймером, план повторов
senior·base — что спрашивают на самом деле
В этом посте были ссылки, но мы их удалили по правилам Сетки