Hibernate Envers — отслеживание версий (ревизий) класса сущности и извлечение ее хронологии

В Hibernate есть модуль, который позволяет отслеживать версии каждой сущности. В этой статье рассмотрим необходимые настройки и протестируем работу Hibernate Envers.

Используемые технологии
  • Hibernate 5.0.1.Final
  • Spring 4.1.5.RELEASE
  • JPA 2.1
  • Maven 3.2.5
  • IntelliJ IDEA 14
  • MySQL 5.6.25

Описание Hibernate Envers

Во многих приложениях необходимо сохранять версии записей (данных) для каждой операции вставки (записи), обновления или удаления. При этом должен быть способ получить определенную версию этой записи. Hibernate Envers (Entity Versioning System — система поддержки версий сущностей) — модуль Hibernate, который специально спроектирован для автоматизации поддержки версий сущностей.

Hibernate Envers поддерживает две различных стратегии аудита:

  1. По умолчанию — Hibernate Envers будет поддерживать столбец для номера версии записи. Каждый раз, когда запись вставляется или обновляется, в таблицу хронологии вставляется новая запись с номером версии, извлеченным из последовательности базы данных или таблицы.
  2. Аудит достоверности — при такой стратегии сохраняются начальная и конечная версии каждой записи хронологии. Каждый раз, когда запись вставляется или обновляется, в таблицу хронологии вставляется новая запись с номером начальной версии. В то же самое время предыдущая запись обновляется номером конечной версии. Также возможно сконфигурировать Hibernate Envers на запись метки времени, когда конечная версия было обновлена, в предыдущей записи хронологии.

1. Описание задачи

Необходимо настроить Hibernate Envers, создать необходимые таблицы и протестировать код, который продемонстрирует как происходит отслеживание версий сущностей.

2. Структура проекта

Проект основан сразу на нескольких статьях, т.к. здесь включены сразу несколько базовых технологий, таких как JPA, Hibernate. Если вам нужно увидеть только настройки, необходимые для Hibernate Envers, то можете переходить к следующему пункту. Если же вам нужны пошаговые инструкции по подключению базы данных, создания классов сущностей, а так же настройки JPA и Hibernate, то вам необходимо прочитать статьи из разделов по Spring Data JPA (раздел JPA) и раздел по Hibernate. Базовые статьи с настройками это: JPA – пример приложения Hello World и Hibernate – быстрый старт. Пример приложения Hello World.

Структура данного проекта:

Hibernate envers structure

В проект подключена таблица MySQL (подключение написано в указанных статьях), создан один интерфейс и его реализация. Имеются два автоматически созданных файла с настройками — spring-config.xml и persistence.xml (этот не используется).

3. Настройки pom.xml

Добавлен необходимый минимум для запуска — две зависимости для spring, две для Hibernate, а так же используемая фреймворком библиотека для JodaTime (они разные для версий до Hibernate 4.0 и после!).

4. Создание таблиц для Hibernate Envers

Базовой таблицей станет ContactAuditEntity (впервые добавлена в Spring Data JPA – отслеживание изменений в сущностном классе (Spring Data JPA Auditing). В неё будут записываться записи, версии которых мы и будем отслеживать.

Отмечу, что указанная чуть выше статья описывает отслеживание лишь изменений в записях (кто и когда создал\изменил запись), но там нет версионирования записей и не предусмотрена возможность вытащить запись определенной версии.

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

Имя первой таблицы строится путем добавления суффикса (указывается в настройках) к базовой таблице. В нашем случае для таблицы Contact_Audit необходимо создать таблицу Contact_Audit_H:

Нас интересуют колонки:

*Следующие колонки в этой статье не используются (остались из проекта по отслеживанию версий в Spring Data JPA):

Вторая необходимая таблица REVINFO (такое название обязательно):

Результат:

Hibernate envers tables

5. Конфигурирование spring-context.xml

Все настройки описаны в статьях о Hibernate и JPA. Для этой статьи добавлены:

Подробнее о добавленных свойствах:

  • audit_table_suffix — суффикс имени таблицы для сущности, для которой отслеживаются версии. Например, для сущностного класса ContactAuditEntity, который отображается на таблицу CONTACT_AUDIT, Hibernate Envers будет сохранять хронологию в таблице CONTACT_AUDIT_H, поскольку свойство audit_table_suffix установлено в _H. О нем писалось чуть выше при создании таблицы.
  • revision_field_name — столбец таблицы хронологии для сохранения номера версии для каждой записи хронологии
  • revision_type_field_name — столбец таблицы хронологии для сохранения типа действия обновления
  • audit_strategy — стратегия аудита, используемая для отслеживания версий сущностей
  • audit_strategy_validity_end_rev_field_name — столбец таблицы хронологии для сохранения номера конечной версии для каждой записи хронологии. Требуется только в случае применения стратегии аудита достоверности
  • audit_strategy_validity_store_revend_timestamp — следует ли сохранять метки времени при обновлении номера конечной версии для каждой записи хронологии. Требуется только в случае применения стратегии аудита достоверности
  • audit_strategy_validity_revend_timestamp_field_name — столбец таблицы хронологии для сохранения метки времени, когда обновляется номер конечной версии для каждой записи хронологии. Требуется только в случае применения стратегии аудита достоверности и при условии, что предыдущее свойство установлено в true

6. Настройка сущностей для отслеживания версий

Сущность ContactAuditEntity:

Для включения Hibernate Envers используются две аннотации @Audited и @NotAudited. С первой думаю всё понятно, а вторая используется на таблицах ассоциациях (@ManyToMany и @OneToMany), т.к. Hibernate автоматически попытается отследить и версии связанных таблиц. В нашем случае это не требуется и мы поставим аннотацию, запрещающую отслеживать какие-либо изменения в сущности ассоциации.

6.1. Извлечение записей хронологии

Hibernate Envers предоставляет интерфейс org.hibernate.envers.AuditReader, который можно получить из класса AuditReaderFactory.

Интерфейс с методом для поиска записи по номеру ревизии ContactAuditService:

Реализация интерфейса (код только для Hibernate Envers) ContactAuditServiceImpl:

Полный листинг ContactAuditServiceImpl :

7. Тестирование приложения

Класс Main:

Сначала создаем новый контакт и записываем в таблицу. Затем находим контакт по id и перезаписываем часть информации. Далее находим записи с различной версией.

Вам для тестирования необходимо комментировать часть кода для вставки первого контакта (т.к. будет дубляж в дальнейшем) и оставлять только пересохранение. Так же id и номер версии вам следует указать свой.

Результат:

Как видите для ревизии 1 и 3 был возвращен корректный результат, показывающий различные версии для контакта с id=8.

Можеть быть интересно

Spring Data JPA Auditing + Hibernate Envers — аудит изменения записи и сохранение ее версий

 

Исходные коды

Hibernate — Envers — src

Hibernate Envers SQL

Share Button
3
2518 Total Views 1 Views Today

Добавить комментарий