Связанный с этим вопросом
Предпосылка:
Это мои предположения, на основе моего чтения, опыта и понимания, они могут быть неправыми, если они, прокомментируйте, и я отредактирую вопрос.
Вопрос:
У меня есть объект, который не находится в 2-м кэше уровня. Из-за некоторого плохого программирования или других ограничений, код, который загружает объект, называют, несколько времен в том же в спящем режиме сессия. retrival использует HQL, находят запрос, например.
hibernateTemplate.find("from Foo f where f.bar > ?", bar);
Перед добавляющим кэшем запроса, если вышеупомянутый код назвали временами N в том же, в спящем режиме Сессия, были хиты N к базе данных
Затем я хотел видеть то, что происходит, если я добавляю кэш запроса:
Query query = session.createQuery("from Foo f where f.bar > ?");
query.setCacheable(true);
query.setParameter(bar);
query.list();
То, когда я добавил кэш запроса, я заметил, что во время той же сессии, будьте в спящем режиме, больше не поражает времена базы данных N, только однажды на сессию.
Foo
) то, которое не находится в 2-м кэше уровня, было изменено в базе данных, затем запросите кэш, будучи перекрестной ограниченной по объему сессией, возвратит неправильные идентификаторы и таким образом неправильные объекты. Это корректно?Между прочим, в связанном вопросе утверждается, что кэш запроса не работает над объемом Кэша Сессии. Я неправильно понимаю то требование или что-либо еще?
Кэш запросов - это особый тип кеша 2-го уровня. То, что вы называете кешем 2-го уровня, я бы предпочел называть «кешем объектов».
Комментарии к вашим предположениям:
- Кэш запросов хорош в основном вместе с кешем 2-го уровня (он же объект кеш).
Кэш запросов содержит только необработанные результаты запросов в качестве первичных ключей, в спящем режиме, идентификаторов. Он не удерживает фактические гидратированные объекты. Это имеет смысл, поскольку когда вы выполняете запрос с помощью jdbc, он фактически возвращает вам гидратированные (заполненные) объекты, когда вы выполняете итерацию по ResultSet. Заявление не обязательно правильное. Если запрос очень сложен и, следовательно, требует очень много времени для выполнения, используя кеш запроса, вы сэкономите это время. Используя кеш запросов, вы не сэкономите время, необходимое для загрузки объектов из базы данных.
- Кэш запросов опасен, если база данных была изменена, и это не отразилось в кэш
Это верно, но это не уникально для кеша запросов, то же самое верно и для того, что вы называете кешем 2-го уровня, но что обычно называется кешем объектов.
Итак, мое первое предположение состоит в том, что Hibernate первые поиски в Сессионный кеш, затем на 2-м уровне Кэш. Верно ли это предположение?
Да, при загрузке объектов происходит такое поведение.
Я также предполагаю, что если объект (Foo) которого нет в кеше 2-го уровня, был изменен в базе данных, затем кеш запросов, являющийся перекрестным сеансом ограниченный, вернет неправильный идентификаторы, и, следовательно, неправильные объекты. Это правильно?
Да, это затронет как кеш объектов, так и кеш запросов. Это вызывает беспокойство только в том случае, если база данных изменяется без перехода в спящий режим. Вы можете уменьшить влияние этого, установив тайм-аут кеша запросов.
Можно ли тогда сказать, что использование кеш запросов для запросов, которые включают неизменяемая информация даже для не 2L кэшированные объекты, это хорошая практика? (например, запрос, в котором его предложение where содержит условие, которое всегда будет вернуть те же результаты, например "Выбрать p.ser_num, где p.id =? "когда ser_num и id пары не меняются ни разу created)
Для таких объектов нет причин не использовать как кеш объектов, так и кеш запросов.
И да, кеш запросов не работает на уровне сеанса, также известном как кеш уровня 1. Таким образом, причина, по которой, когда вы снова выполняете запрос, он снова попадает в базу данных. Он не помещает результат (набор идентификаторов) запроса в кеш сеанса.
Для вопроса #3 я не думаю, что вы хотите использовать кэш запросов, когда объекты не кэшируются. Вы получите все первичные идентификаторы, но для получения объектов, которые могут быть медленнее, чем выполнение запроса без кэширования вообще, придется один раз ударять по базе данных по каждому ключу. В любом случае, начиная с версии 3.3, может быть, в более новых версиях он хватает недостающие объекты, используя меньшее количество запросов, например, where id в (:id1,:id2,...).
.только предположения:
Согласно этой статье из документации Hibernate:
.[кэш запросов] создает два новых кэша. регионы: один запрос с кэшированием наборы результатов (org.hibernate.cache.StandardQueryCache), другие временные метки последние обновления для запрашиваемых таблицы (org.hibernate.cache.UpdateTimestampsCache).
Я предполагаю, что это означает, что всякий раз, когда метка времени в запрашиваемой таблице оказывается более новой, чем набор результатов - это приводит к тому, что при следующем обращении к БД в спящем режиме она приближается к БД, и это то, что в каком-то аспекте обеспечивает сохранность кэша запросов.
Но 2 предложения позже в том же параграфе документации говорится:
Кэш запросов должен всегда использоваться в связи со вторым уровнем кэш
опять же, мое предположение заключается в том, что это единственный способ в спящем режиме узнать об изменениях в базе данных, которые происходят из этого конкретного пользовательского сеанса
.