Подтвердить что ты не робот

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

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

Как Hibernate решает, какие объекты "грязны" и их нужно записать?

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

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

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

4b9b3361

Ответ 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 устанавливает грязный флаг (и выдает обновление), даже если клиент не изменил значение