Почему не работает кэш первого уровня Hibernate в данном примере?
Вот у меня простейший метод
public List<DishResponseDTO> getAll() {
List<Dish> dishlsit = dishRepository.findAll();
return dishlsit.stream()
.map(DishMapper::toDishResponseDTO)
.collect(Collectors.toList());
}
Я его в @SpringBootTest вызываю, но с transactional
@Test
@Transactional
public void get() {
System.out.println(dishService.getAll());
System.out.println(dishService.getAll());
System.out.println(dishService.getAll());
}
Разве он не выполняется в одной сессии, если стоит @Transactional? Почему 3 вызова провоцируют 3 обращения к БД, я думал, что кэш первого уровня hibernate должен решать эти вопросы, если вызовы в границах сессии
Ответы (1 шт):
Кеш первого уровня, грубо говоря, хранит такую структуру данных:
Map<EntityId, Object> entityById;
Т.е. он позволяет получить сущность по идентификатору. Кеш первого уровня действительно привязан к сессии, которая в свою очередь привязана к транзакции. Но так как кеш первого уровня хранит только мапу идентификаторов, то он не работает, когда выполняется любой другой запрос. Как в этом случае, результат запроса "получить все объекты" не может быть воссоздан из кеша первого уровня.
Для такого нужно использовать кеш второго уровня (который в свою очередь не хранит объекты, а только идентификаторы объектов для запроса).
Кеш первого уровня полезен, чтобы не делать дополнительные запросы именно по идентификатору, например, когда несколько записей в результате ссылается на один и тот же ассоциированный объект.