У нас есть приложение, которое использует кэширование 2-го уровня Hibernate, чтобы избежать попаданий в базу данных.
Мне было интересно, есть ли какой-нибудь простой способ аннулировать кэш 2-го уровня приложения Java, когда внешний процесс, такой как администратор MySQL, напрямую подключен для изменения базы данных (обновление / вставка / удаление).
Мы используем EHCache в качестве нашей реализации кэша 2-го уровня.
Мы используем сочетание @Cache (использовании = CacheConcurrencyStrategy.READ_WRITE) и @Cache (использовании = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE), и у нас не включено управление оптимистическим параллелизмом с использованием временных меток для каждого объекта.
SessionFactory содержит методы для управления кешем 2-го уровня:
- Управление кешами
sessionFactory.evict(Cat.class, catId); //evict a particular Cat
sessionFactory.evict(Cat.class); //evict all Cats
sessionFactory.evictCollection("Cat.kittens", catId); //evict a particular collection of kittens
sessionFactory.evictCollection("Cat.kittens"); //evict all kitten collections
Но поскольку мы аннотируем отдельные классы сущностей с помощью @Cache, у нас нет центрального места, чтобы «надежно» (например, без ручных шагов) добавить это в список.
// Easy to forget to update this to properly evict the class
public static final Class[] cachedEntityClasses = {Cat.class, Dog.class, Monkey.class}
public void clear2ndLevelCache() {
SessionFactory sessionFactory = ... //Retrieve SessionFactory
for (Class entityClass : cachedEntityClasses) {
sessionFactory.evict(entityClass);
}
}
Нет никакого реального способа для кэша 2-го уровня Hibernate узнать, что сущность изменилась в БД, если она не запрашивает эту сущность (от чего кеш защищает вас). Поэтому, возможно, в качестве решения мы могли бы просто вызвать какой-либо метод, чтобы заставить кэш второго уровня исключать все (опять же, из-за отсутствия блокировки и контроля параллелизма вы рискуете при выполнении транзакций из-за «чтения» или обновления устаревших данных).