Когда Hibernate сбрасывает сеанс, как он определяет, какие объекты в сеансе загрязнены?

StackOverflow https://stackoverflow.com/questions/82429

Вопрос

Мое понимание гибернации заключается в том, что по мере загрузки объектов из базы данных они добавляются в сеанс.В различные моменты, в зависимости от вашей конфигурации, сеанс сбрасывается.На этом этапе измененные объекты записываются в базу данных.

Как Hibernate определяет, какие объекты являются "грязными" и должны быть записаны?

Перехватывают ли прокси, сгенерированные Hibernate, назначения полям и добавляют ли объект в грязный список в сеансе?

Или Hibernate просматривает каждый объект в Сеансе и сравнивает его с исходным состоянием объектов?

Или что-то совершенно другое?

Это было полезно?

Решение

Hibernate использует / может использовать генерацию байт-кода (CGLIB), чтобы он знал, что поле загрязнено, как только вы вызываете установщик (или даже присваиваете полю afaict).

Это немедленно помечает это поле / объект как загрязненное, но не уменьшает количество объектов, которые необходимо проверить на загрязнение во время очистки.Все, что это делает, - это влияет на реализацию org.hibernate.engine.EntityEntry.requiresDirtyCheck().IT все еще выполняет сравнение по полю, чтобы проверить наличие загрязнений.

Я говорю вышесказанное, основываясь на недавнем просмотре исходного кода (3.2.6GA), со всем доверием, которое это добавляет.Представляющими интерес являются:

  • SessionImpl.flush() запускает onFlush() событие.
  • SessionImpl.list() звонки autoFlushIfRequired() который запускает onAutoFlush() событие.(в таблицах, представляющих интерес).То есть запросы могут вызывать сброс.Интересно, что сброс не происходит, если нет транзакции.
  • Оба эти события в конечном итоге заканчиваются в AbstractFlushingEventListener.flushEverythingToExecutions(), который заканчивается (среди других интересных локаций) в flushEntities().
  • Это перебирает все объекты в сеансе (source.getPersistenceContext().getEntityEntries()) зовущий DefaultFlushEntityEventListener.onFlushEntity().
  • В конце концов вы оказываетесь в dirtyCheck().Этот метод действительно вносит некоторые оптимизации в отношении грязных флагов CGLIB, но в итоге мы все равно перебираем каждую сущность.

Другие советы

Hibernate создает моментальный снимок состояния каждого объекта, который загружается в Сеанс.При сбросе каждый объект в сеансе сравнивается с соответствующим моментальным снимком, чтобы определить, какие из них являются загрязненными.Инструкции SQL выдаются по мере необходимости, и моментальные снимки обновляются, чтобы отразить состояние (теперь чистых) объектов сеанса.

Взгляните на org.hibernate.event.def.DefaultFlushEntityEventListener.dirtyCheck Каждый элемент сеанса обращается к этому методу, чтобы определить, является ли он загрязненным или нет, путем сравнения с нетронутой версией (одной из кэша или одной из базы данных).

Механизм проверки "грязного" режима гибернации по умолчанию будет проходить через текущие подключенные объекты и сопоставлять все свойства с их начальными значениями времени загрузки.

Вы можете лучше представить себе этот процесс на следующей диаграмме:

Default automatic dirty checking

Эти ответы являются неполными (в лучшем случае - я здесь не эксперт).Если у вас есть объект hib man в вашем сеансе, вы НИЧЕГО с ним не ДЕЛАЕТЕ, вы все равно можете получить обновление при вызове функции save() для него.когда?когда другой сеанс обновляет этот объект между вашими load() и save().вот мой пример этого: режим гибернации устанавливает грязный флаг (и выдает обновление), даже если клиент не изменил значение

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top