Может показаться, что вы либо
- вручную заполняете базу данных и обходите Hibernate
- Включение Hibernate Envers для сопоставления сущностей, в котором уже есть данные
Для того чтобы Envers мог реагировать на изменения, важно, чтобы изменения в базе данных были выполнены через Hibernate, чтобы его структура событий запускала всех слушателей Envers, которые отвечают за генерацию истории аудита. Если какой-либо шаг обходит это, запись аудита не будет сгенерирована.
Envers также не генерирует историю аудита для сопоставления сущностей, в котором уже есть данные. Ожидается, что ваша таблица сущностей будет пустой, а события вставки, обновления и удаления будут перехвачены Hibernate, распространены в Envers, и история аудита будет видоизменяться в зависимости от них. С существующими данными нет событий, и, следовательно, история аудита не генерируется автоматически. Разработчик должен правильно seed история аудита, если вы собираетесь включить аудит для таблиц с существующими данными.
Так что, если мы отступим и предположим, что вы не сделали вручную запустите или включите Envers для объекта с данными, которые уже существовали в базовой таблице ORM, тогда ваша таблица аудита должна была выглядеть после обновления:
+---+--------------------+-----+-----+---------+
|Id | User | Age | REV | REVTYPE |
+---+--------------------+-----+-----+---------+
| 1 | Foo Bar | 35 | 1 | 0 |
| 2 | Bar Foo | 40 | 1 | 0 |
| 3 | Bob Dixon | 50 | 1 | 0 |
| 4 | Alice Spolsky | 59 | 1 | 0 |
| 1 | Foo Bar | 55 | 2 | 1 |
+---+--------------------+-----+-----+---------+
Вы заметите столбец REVTYPE
. Этот столбец представляет операцию, связанную с мутацией строки. Эти значения являются частью типа перечисления, где:
- 0 = INSERT
- 1 = UPDATE
- 2 = DELETE
Envers Query API позволяет вам получить список номеров ревизий для первичного ключа данного объекта, и оттуда вы можете выбрать каждую ревизию и выполнить различие между экземплярами объекта, используя любую библиотеку diff или написать свою собственную.
Envers такжеподдерживает атрибут аннотации с именем withModifiedFlags
. Это отключено по умолчанию, поскольку добавляет в модель сущности довольно много дополнительных столбцов поддержки, но при включении ваша модель будет выглядеть следующим образом:
+---+--------------------+----------+-----+---------+-----+---------+
|Id | User | User_MOD | Age | Age_MOD | REV | REVTYPE |
+---+--------------------+----------+-----+---------+-----+---------+
| 1 | Foo Bar | 1 | 35 | 1 | 1 | 0 |
| 2 | Bar Foo | 1 | 40 | 1 | 1 | 0 |
| 3 | Bob Dixon | 1 | 50 | 1 | 1 | 0 |
| 4 | Alice Spolsky | 1 | 59 | 1 | 1 | 0 |
| 1 | Foo Bar | 0 | 55 | 1 | 2 | 1 |
+---+--------------------+----------+-----+---------+-----+---------+
Эти столбцы _MOD
полезны, так какпозволяет создавать сложные запросы, чтобы проверить, изменились ли определенные интересующие столбцы в ревизии. Хотя это не позволяет вам получить предыдущее значение из текущей строки аудита, эту информацию можно вывести, посмотрев историю таблицы аудита для первичного ключа этого объекта.
Возможно, вы спросите, может ли Энверсдобавьте эти _MOD
столбцы, почему бы не эти столбцы "предыдущего значения". Теоретически мы могли бы сделать это, но я считаю важным сделать шаг назад и измерить, будет ли это действительно ценно.
Я думаю, что было бы гораздо полезнее усовершенствовать API запросов таким образом, чтобы пользователь мог попросить Envers представить некоторое представление истории сущности, возможно, различия между двумя конкретными ревизиями или, возможно, в течение времени жизни междудве ревизии. Это представление позволит вам получить предыдущие и текущие значения из него.
Короче говоря, тогда не нужно будет менять схему, поскольку API сделает это для вас исключительно праматично.