2012-05-10 2 views
7

У меня возникли проблемы с пониманием, откуда запрос HQL получает информацию. Мой проект использует разные потоки, и каждый поток читает/записывает в базу данных. Темы не разделяют объекты Session, вместо этого я использую класс HibernateUtil, который создает сеансы для меня.Hibernate HQL только попадает в кеш сеанса

До недавнего времени я только закрыл сессию после написания, но не после прочтения. Изменения в объектах будут немедленно замечены в базе данных , но при чтении в других потоках (другой объект сеанса, чем тот, который используется для записи). Я получил бы устаревшую информацию. Чтение и запись происходили всегда на разных потоках, что означает разные объекты сеанса и разные сеансовые кеши.

Я всегда думал, что с помощью HQL вместо Criteria, я всегда целевой базы данных (или кэш второго уровня), а не кэш сеанса, но при отладке мой код, это было сделано для меня ясно, что HQL искал объект в кеше сеанса и извлекает старый устаревший объект.

Я ошибался, полагая, что HQL всегда нацелен на базу данных? Или, по крайней мере, кэш второго уровня?

PS: Я использую только один объект SessionFactory.

ответ

7

Hibernate имеет различные концепции кэширования - сущности объектов и кеши запросов. Кэширование объектов - это то, что делает кеш сеанса (и кеш второго уровня, если он включен).

Предполагая, что кеширование запросов не включено (это не по умолчанию), ваш HQL был бы выполнен против базы данных. Это вернет идентификаторы объектов, которые соответствуют запросу. Если эти объекты уже находятся в кеше сеанса, то Hibernate вернул их, а не восстановил их из базы данных. Если ваш сеанс имеет устаревшие копии (потому что другой сеанс обновил базу данных), то это проблема, которая у вас есть.

Я бы посоветовал использовать длительные сессии, главным образом по этой причине. Вы должны ограничить продолжительность сеанса определенной частью работы, которую вы пытаетесь сделать, а затем закрыть ее. Этого мало или вообще не нужно делать, если вы используете пул соединений с базой данных. Кроме того, чтобы убедиться, что вы не получаете устаревшие объекты, вы можете позвонить по номеру Session.clear(), но вы можете столкнуться с неожиданными побочными эффектами.

+0

поэтому первый раз, когда мой объект сеанса выполняет запрос HQL, он нацелен на db. результат затем сохраняется в кеше сеанса. то во второй раз, когда я выполняю тот же запрос HQL, он считывает кеш вместо таргетинга на базу данных. это поведение по умолчанию. Я понял это правильно? ** ps: ** действительно, закрытие сессий после каждого чтения и записи (короткие объекты 'Session') решает мою проблему. – alegen

+4

@alegen: HQL будет запускаться в базе данных * каждый раз *, но объекты Java, являющиеся конечным результатом этого запроса, могут поступать из кеша сеанса. Это поведение по умолчанию. – skaffman

+1

у вас сэр отличный день! Спасибо за ответ :) – alegen