#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
, если хотите (при условии, что последнее устаревшее изменение = снимок текущей записи).