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




Hibernate делает снимок состояния каждого объекта, загружаемого в сеанс. При сбросе каждый объект в сеансе сравнивается с его соответствующим снимком, чтобы определить, какие из них загрязнены. Операторы SQL выдаются по мере необходимости, и моментальные снимки обновляются, чтобы отразить состояние (теперь чистых) объектов сеанса.
Взгляните на org.hibernate.event.def.DefaultFlushEntityEventListener.dirtyCheck Каждый элемент в сеансе обращается к этому методу, чтобы определить, загрязнен он или нет, сравнивая его с нетронутой версией (один из кеша или один из базы данных).
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, но мы все равно перебираем каждую сущность в цикле.Пожалуйста, объясните лучше: если грязный флаг не уменьшает количество объектов, которые нужно грязно-проверять, в чем его полезность? Более того, в источнике я вижу два разных грязных флага: один находится в AbstractFieldInterceptor и проверяется EntityEntry.requiresDirtyCheck (), другой находится в AbstractPersistentCollection и комментируется: «коллекции обнаруживают изменения, внесенные через их открытый интерфейс, и помечают себя как грязные, как производительность. оптимизация »(не знаю, где это проверено в коде).
@Matt Quail, я не смог найти грязные флаги, о которых вы говорите, есть только тот, который можно использовать, только если используется инструментарий байт-кода времени сборки.
Механизм грязной проверки Hibernate по умолчанию будет проходить по текущим присоединенным объектам и сопоставлять все свойства с их начальными значениями времени загрузки.
Вы можете лучше представить себе этот процесс на следующей диаграмме:

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