Способ работы кэша запросов заключается в том, что он кэширует только ID объектов, возвращаемых запросом. Итак, ваш первоначальный оператор SELECT может вернуть все объекты, и Hibernate вернет их вам и запомнит идентификаторы.
Однако в следующий раз, когда вы выполните запрос, Hibernate просматривает список идентификаторов и понимает, что ему необходимо материализовать фактические данные. Так что возвращается в базу данных, чтобы получить остальное. И он делает один SELECT для каждой строки, и это именно то, что вы видите.
Теперь, прежде чем вы подумаете, что «эта функция явно не работает», причина, по которой она работает таким образом, заключается в том, что Query Cache предназначен для работы совместно с кэшем второго уровня. Если объекты сохраняются в кеше L2 после первого запроса, Hibernate будет искать их там, чтобы удовлетворить запросы для каждого ID.
Я настоятельно рекомендую вам взять книгу Сохранение Java с Hibernate , чтобы узнать больше об этом. В частности, глава 13 посвящена оптимизации запросов и тому, как эффективно использовать кэш.