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

17

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

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

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

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

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

    
задан tgdavies 17.09.2008 в 14:13
источник

5 ответов

22

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, но мы все же закончили цикл по каждому объекту.
ответ дан Matt Quail 17.09.2008 в 15:07
  • Пожалуйста, объясните лучше: если грязный флаг не уменьшает количество объектов, которые должны быть грязно проверены, в чем его польза? Furtermore в источнике я вижу два разных грязных флага: один находится в AbstractFieldInterceptor и проверен EntityEntry.requiresDirtyCheck (), другой - в AbstractPersistentCollection и прокомментирован: «коллекции обнаруживают изменения, сделанные через их публичный интерфейс, и отмечают себя настолько же грязными, как производительность оптимизация "(я не знаю, где это проверено в коде). –  Pino 14.09.2012 в 16:38
  • @Matt Quail, я не мог найти грязные флаги, о которых вы говорите, есть только тот, который можно использовать, только если используется инструментарий байт-кода времени сборки. –  Stanislav Bashkyrtsev 28.09.2014 в 07:57
5

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

    
ответ дан alasdairg 17.09.2008 в 14:35
  • В спящем режиме ситуация описывается следующим образом: атрибут по атрибуту сравнения объектов моментальных снимков с объектами сеанса. Это контрастирует с Datanucleus (в режиме JDO или JPA), где его усиление байт кода позволяет ему делать очень умные, высокоэффективные вещи, такие как добавление грязного флага в каждый упорный класс. Это означает, что во время флеша в Datanucleus грязность любого объекта - это простая проверка грязного флага. Вам не нужно быть Эйнштейном, чтобы понять, почему с любой нетривиальной объектно-ориентированной моделью домена, почему флеш Hibernate занимает намного больше времени. –  Volksman 15.03.2014 в 00:24
1

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

ответ дан JeroenWyseur 17.09.2008 в 14:36
1

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

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

    
ответ дан Vlad Mihalcea 21.08.2014 в 13:20
0

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

    
ответ дан tom 22.12.2014 в 15:58