Автор оригинала: Vlad Mihalcea.
Hibernate запускает механизм автоматической проверки на загрязнение во время промывки, и любое изменение состояния управляемой сущности преобразуется в инструкцию UPDATE
SQL. Механизм проверки на загрязнение по умолчанию использует отражение Java и проходит через каждое свойство каждого управляемого объекта.
Если контекст сохранения содержит несколько сущностей, этот процесс может остаться незамеченным, но если мы имеем дело со многими сущностями или у сущностей много свойств (например, сопоставление устаревшей модели домена базы данных), то проверка на основе отражения может повлиять на производительность.
Hibernate предлагает поддержку инструментального байт-кода сущностей для трех вариантов использования:
- ленивая инициализация (позволяет лениво извлекать атрибуты сущности)
- грязное отслеживание (сущность отслеживает изменения своих собственных свойств)
- управление ассоциациями (позволяет автоматически синхронизировать стороны для двунаправленных ассоциаций)
Несмотря на то, что он включал инструмент улучшения байт-кода начиная с версии 3.x, даже в режиме гибернации 4.x механизм улучшения байт-кода не был полностью реализован для проверки на наличие ошибок.
Среди многих других функций Hibernate 5.x поставляется с совершенно новой реализацией улучшения байт-кода, которая также устраняет механизм проверки на наличие ошибок. Хотя улучшение байт-кода может быть выполнено во время компиляции, во время выполнения или во время развертывания, альтернатива во время компиляции предпочтительна по следующим причинам:
- расширенные классы могут быть охвачены модульными тестами
- сервер приложений Java EE или автономный контейнер (например, Spring) могут загружаться быстрее, поскольку нет необходимости настраивать классы во время выполнения или во время развертывания
- проблем с загрузкой классов можно избежать, так как серверу приложений не нужно заботиться о двух версиях одного и того же класса (исходной и расширенной).
Чтобы использовать все классы @Entity
, вам необходимо добавить следующий плагин Maven:
org.hibernate.orm.tooling hibernate-enhance-maven-plugin ${hibernate.version} true enhance
После компиляции классов Java плагин проходит через все классы сущностей и изменяет их байт-код в соответствии с параметрами инструментария, выбранными во время настройки.
При включении параметра отслеживание ошибок Hibernate будет отслеживать изменения свойств с помощью следующего механизма. Атрибут $$_hibernate_tracker
хранит каждое изменение свойства, и каждый метод настройки вызовет $$_hibernate_trackChange
метод.
@Transient private transient DirtyTracker $$_hibernate_tracker; public void $$_hibernate_trackChange(String paramString) { if (this.$$_hibernate_tracker == null) { this.$$_hibernate_tracker = new SimpleFieldTracker(); } this.$$_hibernate_tracker.add(paramString); }
Учитывая следующий оригинальный метод задания классов сущностей Java:
public void setTitle(String title) { this.title = title; }
Hibernate преобразует его в следующее представление байт-кода:
public void setTitle(String title) { if(!EqualsHelper.areEqual(this.title, title)) { this.$$_hibernate_trackChange("title"); } this.title = title; }
Когда разработчик приложения вызывает метод setTitle
с аргументом, отличным от сохраненного в данный момент заголовка
, изменение будет записано в атрибуте класса $$_hibernate_tracker
.
Во время очистки Hibernate проверяет метод $$_hibernate_hasDirtyAttributes
, чтобы проверить, является ли объект загрязненным. Метод $$_hibernate_getDirtyAttributes
выдает Строку []
, содержащую все грязные свойства.
public boolean $$_hibernate_hasDirtyAttributes() { return $$_hibernate_tracker != null && !$$_hibernate_tracker.isEmpty(); } public String[] $$_hibernate_getDirtyAttributes() { if($$_hibernate_tracker == null) { $$_hibernate_tracker = new SimpleFieldTracker(); } return $$_hibernate_tracker.get(); }
Хотя отслеживание “грязного” байт-кода может ускорить механизм очистки контекста сохранения, если размер контекста сохранения довольно мал, улучшение не столь значительно.
Снимок сущности по-прежнему сохраняется в контексте сохранения даже при использовании улучшения байт-кода. По этой причине сохранение контекста сохранения в разумных границах сохраняется независимо от используемого механизма отслеживания ошибок.