Как ограничить типы аудитов в Hibernate Envers

#java #hibernate #audit #hibernate-envers

#java #спящий режим #аудит #hibernate-envers

Вопрос:

Я пытаюсь выполнить свою первую реализацию Hibernate Envers. У меня есть все мои теги @Audited на месте, и я генерирую DDL для создания таблиц аудита.

Из того, что я прочитал, таблицы аудита будут получать запись каждый раз, когда проверяемая таблица получает новую запись, запись изменяется или запись удаляется.

В моей реализации меня действительно волнуют только изменения, и поскольку я читал, что аудит снижает производительность, я хотел бы отключить то, что мне не нужно.

Мне было трудно найти информацию об этом. Единственное, что было близко, это то, что мне нужно было бы отключить все прослушиватели Envers и повторно реализовать их самостоятельно, заставив те, которые я не хочу, ничего не делать.

Это кажется большой работой, и я уже нахожусь на неизведанной территории. Кто-нибудь знает простой способ сделать это? В противном случае у кого-нибудь есть какой-нибудь код, которым они могут поделиться, показывающий, как это сделать?

Спасибо,

Комментарии:

1. Я понимаю ваши проблемы с производительностью, но, учитывая вашу реализацию; вы профилировали и определили, есть ли какие-либо основания для вашей озабоченности? Envers используется рядом крупных частных организаций, управляющих миллионами строк с минимальными накладными расходами или вообще без них. Возможно, вы сможете более конкретно описать интересующий вас вариант использования, и я буду рад предоставить ответ.

Ответ №1:

Короткий ответ здесь — нет, не существует.

Единственная доступная опция переключения, которая подходит близко, — это указать Envers, следует ли ему проверять все данные столбца в строках типа ревизии DEL или нет. Поведение по умолчанию заключается не в том, чтобы включать все значения столбца при удалении объекта; однако бывают случаи, когда сохранение этой информации может быть весьма полезным.

Кроме того, это не просто случай предотвращения регистрации определенного прослушивателя Envers, и это не так просто, как перекодирование определенного прослушивателя.

Давайте рассмотрим некоторые варианты использования

 // Fetch the parent
Parent parent = entityManager.find( Parent.class, parentId );

// Add a new child entity to parent
entityManager.getTransaction().begin();
Child child = new Child( "Naros" );
child.setParent( parent );
parent.getChildren().add( child );
entityManager.persist( child );
entityManager.merge( parent );    
entityManager.getTransaction().commit();

// Update a child entity 
entityManager.getTransaction().begin();
child.setName( "Naros2" );
entityManager.merge( child );
entityManager.getTransaction().commit();

// Remove child entities from parent
entityManager.getTransaction().begin();
parent.getChildren().forEach( c -> c.setParent( null ) );
parent.getChildren().clear();
entityManager.merge( parent );
entityManager.getTransaction().commit();
  

Во всех 3 случаях, приведенных выше, Parent объект будет проверен с помощью MOD исправленной записи, которая описывает, что она была изменена в определенное время с заданным номером редакции.

Аналогично, первый сценарий будет содержать ADD исправленную запись для того, Child когда она была добавлена в родительскую коллекцию. Это будет включать тот же номер редакции, что и первая редакция Parent .

Второй сценарий будет содержать MOD исправленную запись для того, Child когда она была изменена. В зависимости от типа коллекции в родительской, влияют ли внесенные вами изменения на порядок коллекции, возможно, что MOD также будет инициировано для Parent объекта.

Последний сценарий будет содержать DEL исправленную запись для Child , когда она будет удалена из коллекции, и MOD поскольку состояние родительского элемента было изменено.

Можно ли отключить этот тип поведения, да. Но проблема в том, что при этом вы теряете некоторые действительно ценные функциональные возможности.

Например, Parent будет содержать строки аудита только тогда, когда вы фактически изменили свойство Parent , а не когда вы изменяете какие-либо свойства коллекции, которые связаны с ним. Это означает, что в простом примере Parent будет иметь только 1 строку аудита, ADD когда она была вставлена.

Но что, если вам нужно знать фактическое состояние Parent на каждом пересмотренном шаге после внесения изменений в дочернюю коллекцию? Ну, вы не можете.

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

Но попытка отключить аспекты Envers может и, вероятно, будет иметь негативные последствия с точки зрения аудита, если вы это сделаете.

Комментарии:

1. Спасибо за информацию. Я читал о проблемах с производительностью, которые имели смысл для меня, если приложение дублирует классы и постоянно их поддерживает. Однако, если вы говорите, что это не так уж много для hit, я согласен с этим.

2. Я выполняю миграцию из другой системы, в которой также был аудит, но только по изменениям. Я планировал перенести изменения в таблицы аудита вручную. Целесообразно ли это? Вы бы создали только записи изменений или мне следует создать самую старую ревизию в качестве записи добавления?

3. Если у вас есть четкое представление о схеме таблицы аудита и о том, как работают номера ревизий и т.д., То вы, безусловно, можете перенести свою старую историю аудита в схему Envers. Вы бы просто внесли первую запись изменения из устаревшей системы как ADD и другие MOD . Конечно, если вся эта устаревшая информация не важна, вы, безусловно, можете перенести только последнюю запись в качестве ADD , если хотите (при условии, что последнее устаревшее изменение = снимок текущей записи).