HIbernate Envers: внешний ключ к пересмотру - PullRequest
0 голосов
/ 25 сентября 2018

Можно ли добавить внешний ключ к ревизии объекта?

Например, если у меня есть объект Person:

@Entity
@Audited
public class Person {
    @Id
    @Column
    private Integer idPerson;
    @Column
    private String favoriteHobby;
}

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

В SQL это может быть достигнуто путем создания таблицы со столбцами idPerson, idRevision и idYearBook.

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

1 Ответ

0 голосов
/ 01 октября 2018

Чтобы ответить на ваш вопрос сначала из комментариев, Да.

Если вы пометили обе сущности как @Audited, любое изменение, внесенное вами в любую из этих сущностей, приведет к созданию новой строки аудита в схеме аудита.для этого конкретного объекта.

API AuditReader имитирует большую часть старого API Hibernate Criteria.По сути, вы можете построить любой запрос на основе проверяемого типа объекта и применить множество условий для фильтрации результатов.

Здесь есть одна оговорка, которую я хочу упомянуть.

Предположим, что в транзакции мы создаем Person и помещаем их в YearBook:

final Session session = openSession();
try {
   session.getTransaction().begin();

   final Person person = new Person();
   person.setName( "John Doe" );
   person.setHobby( "Plays Guitar" );
   session.save( person );

   final YearBook yearBook = new YearBook();
   yearBook.setYear( 2018 );
   yearBook.getPeople().add( person );
   session.save( yearBook );

   session.getTransaction().commit();
}
catch( Exception ex ) {
   if ( session.getTransaction().isActive() ) {
     session.getTransaction().rollback();
   }
   throw ex;
}
finally {
  session.close();
}

Это будет означать, что в схеме аудита новая строка аудита будетбыть создан для обоих типов сущностей, и эти строки будут связаны с одним и тем же номером редакции.Для простоты предположим, что это номер редакции 1 .

В будущей транзакции вы измените Person для этого John Doe :

final Session session = openSession();
try {
  session.getTransaction().begin();

  final Person person = session.find( Person.class, personId );
  person.setHobby( "Video Games" );

  session.getTransaction().commit();
}
catch( Exception ex ) {
   if ( session.getTransaction().isActive() ) {
     session.getTransaction().rollback();
   }
   throw ex;
}
finally {
  session.close();
}

На данный момент:

  • YearBook как одна ревизия, ревизия # 1 .
  • Person для John Doe имеет две ревизии, ревизии # 1 и # 2 .

Предостережение заключается в том, что запросы к YearBook запрашивают ревизию 1 никогда не вернет вам ничего о Person в редакции 2 .Это определенно желаемый результат почти во всех случаях;однако существуют некоторые уникальные ситуации, когда пользователи хотят, чтобы YearBook тоже инициировал ревизию.

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

Тем не менее, как бы вы получили YearBook в его ревизиях??Это довольно просто, используя AuditReader API:

final AuditReader reader = AuditReaderFactory.get( session );

// Get the revisions in ascending order from smallest to highest rev #
List<Number> revisions = reader
  .forRevisionsOfEntity( YearBook.class, false )
  .getResultList();

Если вы уже знаете интересующий вас номер редакции, вы можете получить точный снимок этой сущности, используя:

final AuditReader reader = AuditReaderFactory.get( session );
final YearBook yearBook = reader.find( YearBook.class, yearBookId, revision );

Ознакомьтесь с документацией по всем остальным способам создания запросов с использованием интерфейса AuditReader, предоставленного Envers.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...