Когда Hibernate сбрасывает сеанс, как он определяет, какие объекты в сеансе являются грязными? - PullRequest
17 голосов
/ 17 сентября 2008

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

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

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

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

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

Ответы [ 5 ]

22 голосов
/ 17 сентября 2008

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, но мы все равно в конечном итоге зациклились на каждой сущности.
5 голосов
/ 17 сентября 2008

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

1 голос
/ 21 августа 2014

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

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

Default automatic dirty checking

1 голос
/ 17 сентября 2008

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

0 голосов
/ 22 декабря 2014

Эти ответы неполные (в лучшем случае - я здесь не эксперт). Если в вашем сеансе есть объект Hib Man, вы НИЧЕГО не делаете, вы все равно можете получить обновление, когда вызываете save () для него. когда? когда другой сеанс обновляет этот объект между вашими load () и save (). Вот мой пример этого: hibernate устанавливает грязный флаг (и выдает обновление), даже если клиент не изменил значение

...