Когда Hibernate сбрасывает сеанс, как он решает, какие объекты в сеансе загрязнены?
Мое понимание Hibernate заключается в том, что, поскольку объекты загружаются из БД, они добавляются в сеанс. В разных точках, в зависимости от вашей конфигурации, сеанс очищается. На данный момент модифицированные объекты записываются в базу данных.
Как Hibernate решает, какие объекты "грязны" и их нужно записать?
Профили, сгенерированные Hibernate, перехватывают назначения для полей и добавляют объект к грязному списку в сеансе?
Или Hibernate просматривает каждый объект в сеансе и сравнивает его с исходным состоянием объектов?
Или что-то совсем другое?
Ответы
Ответ 1
Hibernate делает/может использовать генерацию байт-кода (CGLIB), так что он знает, что поле грязно, как только вы вызываете сеттер (или даже назначаете поле afaict).
Это сразу же отмечает, что поле/объект является грязным, но не уменьшает количество объектов, которые должны быть грязно проверены во время флеша. Все это влияет на реализацию org.hibernate.engine.EntityEntry.requiresDirtyCheck()
. Он по-прежнему проводит сопоставление по полям для проверки на загрязнение.
Я говорю выше, основываясь на недавнем трауле через исходный код (3.2.6GA), с любой достоверностью, которая добавляется. Достопримечательности:
-
SessionImpl.flush()
запускает событие onFlush()
.
-
SessionImpl.list()
вызывает autoFlushIfRequired()
, который вызывает событие onAutoFlush()
. (по таблицам интересов). То есть, запросы могут вызвать флеш. Интересно, что никакой флеш не происходит, если нет транзакции.
- Оба этих события в конечном итоге заканчиваются на
AbstractFlushingEventListener.flushEverythingToExecutions()
, который заканчивается (среди других интересных мест) в flushEntities()
.
- Это цикл для каждого объекта в сеансе (
source.getPersistenceContext().getEntityEntries()
), вызывающего DefaultFlushEntityEventListener.onFlushEntity()
.
- В конечном итоге вы получите
dirtyCheck()
. Этот метод делает некоторые оптимизации для грязных флагов CGLIB, но мы все же закончили цикл по каждому объекту.
Ответ 2
Hibernate принимает моментальный снимок состояния каждого объекта, который загружается в сеанс. В режиме flush каждый объект в сеансе сравнивается с соответствующим снимком, чтобы определить, какие из них загрязнены. Операторы SQL выдаются по мере необходимости, а моментальные снимки обновляются, чтобы отражать состояние (теперь очищенных) объектов сеанса.
Ответ 3
Взгляните на org.hibernate.event.def.DefaultFlushEntityEventListener.dirtyCheck
Каждый элемент сеанса переходит к этому методу, чтобы определить, является ли он грязным или нет, сравнивая его с нетронутой версией (один из кеша или один из базы данных).
Ответ 4
Механизм грязной проверки по умолчанию Hibernate будет перемещать текущие прикрепленные объекты и сопоставлять все свойства с их начальными значениями времени загрузки.
Вы можете лучше визуализировать этот процесс на следующей диаграмме:
![Default automatic dirty checking]()
Ответ 5
Эти ответы неполны (в лучшем случае - я не эксперт здесь). Если у вас есть сущность hib man в вашем сеансе, вы НЕ НИЧЕГО этого делаете, вы все равно можете получить обновление, выданное при вызове save() на нем. когда? когда другой сеанс обновляет этот объект между вашими нагрузками() и save(). вот мой пример: hibernate устанавливает грязный флаг (и выдает обновление), даже если клиент не изменил значение