Автор оригинала: 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();
}
Хотя отслеживание “грязного” байт-кода может ускорить механизм очистки контекста сохранения, если размер контекста сохранения довольно мал, улучшение не столь значительно.
Снимок сущности по-прежнему сохраняется в контексте сохранения даже при использовании улучшения байт-кода. По этой причине сохранение контекста сохранения в разумных границах сохраняется независимо от используемого механизма отслеживания ошибок.