как остановить запрос по умолчанию для идентификатора при использовании аннотации @cacheable - PullRequest
0 голосов
/ 23 февраля 2020

При использовании аннотации @Cacheable (org.springframework.cache.annotation.Cacheable) в хранилище с настраиваемым ключом, таким как имя, возникает проблема запуска дополнительного запроса в поле id для каждого последовательного запроса.

См. Код хранилища ниже:

public interface StatusRepository extends JpaRepository<Status, Integer> {

    @Cacheable(value = "StatusByStatusNameCache" , key="#statusName")
    public Status findByStatusName(String statusName);

}

Выше видно, что кеш определен только для имени статуса, теперь после запуска первого запроса получил следующую консоль Hibernate с запросом на имя статуса:

Hibernate: select status0_.status_id as status_i1_7_, status0_.status_name as status_n2_7_ from status status0_ where status0_.status_name=?
Hibernate: select event0_.event_id as event_id1_3_, event0_.event_name as event_na2_3_ from events event0_ where event0_.event_name=?

теперь нажмите еще один второй запрос, получая запрос гибернации в консоли с идентификатором:

Hibernate: select event_.event_id, event_.event_name as event_na2_3_ from events event_ where event_.event_id=?
Hibernate: select requestcha_.request_channel_id, requestcha_.request_channel_name as request_2_6_ from request_channels requestcha_ where requestcha_.request_channel_id=?
Hibernate: select status_.status_id, status_.status_name as status_n2_7_ from status status_ where status_.status_id=?

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

1 Ответ

2 голосов
/ 24 февраля 2020

Аннотация @Cacheable от Spring полностью независима от любого кэша, предоставляемого Hibernate / вашей реализацией JPA.

Запрос по идентификатору не будет предотвращен путем кэширования результата запроса по имени, поскольку кеширование для запроса id будет выполняться кешем первого уровня JPAs, который не знает или не заботится о кеше Springs.

Вот что, вероятно, происходит:

  1. findbyName

    объект находится в кэше 1-го уровня и в кэше Springs.

  2. Любой доступ по идентификатору (например, переход к объекту)

    объект обслуживается из кэша 1-го уровня.

  3. сеанс заканчивается.

    объект удаляется из кэша 1-го уровня

  4. findByName

    сущность обслуживается из кэша Springs. Обратите внимание, что теперь это отдельная сущность. В кеше 1-го уровня ничего нет.

  5. доступ по идентификатору

    объект загружен из базы данных, поскольку он не найден в кеше 1-го уровня.

Вы должны включить Hibernates кэш 2-го уровня для кэширования сущностей между сеансами для доступа по идентификатору.

Я также не рекомендовал бы объединять кэши JPA / Hibernate с Spring кэширует, а лучше использовать собственный кэш запросов JPA для кэширования findByName. См. Spring JPA. Кэш запросов Hibernate не работает , чтобы узнать, как заставить его работать с Spring Data JPA.

Также взгляните на эту статью Влад Михалча о взаимодействии запросов. кэш и кэш 2-го уровня .

Обратите внимание, что Оливер Дротбом, похоже, придерживается другого мнения .

...