Кэш первого уровня гибернации - синхронизируется ли он?

Мне известно, что Session – это кеш первого уровня, используемый Hibernate, и как только мы извлекаем объект из session, последующие вызовы get для того же объекта с < em>тот же идентификатор извлекается из session вместо БД, пока session не станет открытым.

Сказав это, у меня есть сомнения относительно того, как спящий режим синхронизирует кеш первого уровня с БД? Рассмотрим следующий сценарий

//Lets say I have created the session

Session s1 = sessionFactory.getSession();
User u1 = s1.get(User.class, 1); //Getting User with ID=1
//s1 is not yet closed

//Lets say I create some other session

Session s2 = sessionFactory.getSession();
User u2 = s2.get(User.class, 1); //Getting User with ID=1
u2.setName("Abc"); // Changed a field
s2.save(u2); // Saved the changes to DB
s2.close(); //Closed the 2nd session

//Now when I once again retrieve User with ID=1 from s1, will I get updated User?
User u3 = s1.get(User.class, 1);// Here as per my understanding cache is used

Итак, мой вопрос

  • Поскольку u3 извлекается из кеша 1-го уровня, имеет ли u3 обновленное значение?
  • Если кто-то напрямую обновляет БД и изменяет объект пользователя, когда сеанс открыт, синхронизируется ли session с БД?

Заранее спасибо за ваше время и усилия в этой теме


person sanbhat    schedule 10.09.2013    source источник


Ответы (3)


Нет, Hibernate ничего не делает для синхронизации состояния сущностей в кеше сеанса с БД, если вы не запросите это явно.

Обычно это не проблема, потому что активная работа обычно происходит внутри транзакции, а операции внутри транзакции не должны видеть изменения, сделанные другими параллельными транзакциями (хотя подробности зависят от уровня изоляции). Таким образом, поведение Hibernate дополняет типичную семантику изоляции транзакций в данном случае.

Также могут быть ситуации, когда необходимо явно синхронизировать состояние объекта, чтобы отразить изменения, сделанные внутри той же транзакции. Это может быть вызвано массовыми запросами на обновление или выполнением триггеров базы данных. В этом случае вам необходимо явно запросить такую ​​синхронизацию, вызвав refresh().

person axtavt    schedule 10.09.2013

Вам нужно будет вызвать Session.evict(Object) на s1 с u1 в качестве аргумента, чтобы получить новый поиск. В качестве альтернативы в этом случае вы также можете вызвать Session.clear() на s1, чтобы получить тот же эффект. Вы также можете вызвать Session.refresh(Object object), чтобы просто обновить состояние u1.

Обратите внимание, что транзакции могут занять неопределенное количество времени (хотя обычно не очень много времени), чтобы другие клиенты увидели их после их фиксации. Обновление может быть не сразу видно другим сеансам, использующим другие подключения.

person Dev    schedule 10.09.2013

Кэш первого уровня (уровня сеанса) гарантирует, что состояние постоянных экземпляров, загруженных одной транзакцией, изолировано от изменений, внесенных другими транзакциями.

Таким образом, изменения, сделанные s2 в другой транзакции (T2), не видны, когда вы вызываете s1.get(User.class, 1) в первой транзакции, потому что на этот раз Hibernate извлечет User из кэша уровня сеанса s1.

person Debojit Saikia    schedule 10.09.2013