Как удалить записи из моей таблицы аудита? - PullRequest
5 голосов
/ 07 мая 2010

В настоящее время я работаю с Hibernate Envers.

Как удалить записи в таблице аудита, связанные с сущностью, которую я хочу удалить? Моя сущность не имеет отношения к другим сущностям.

Я понял, что должен сделать это в onPostDelete методе моего пользовательского слушателя:

import org.hibernate.envers.event.AuditEventListener;
import org.hibernate.event.PostCollectionRecreateEvent;
import org.hibernate.event.PostDeleteEvent;
import org.hibernate.event.PostInsertEvent;
import org.hibernate.event.PostUpdateEvent;
import org.hibernate.event.PreCollectionRemoveEvent;
import org.hibernate.event.PreCollectionUpdateEvent;

public class MyListener extends AuditEventListener {

  ...
  @Override
  public void onPostDelete(PostDeleteEvent arg0) {
    // TODO Auto-generated method stub
    super.onPostDelete(arg0);
  }
  ...

}

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

Кто-нибудь когда-либо делал это раньше?

Ответы [ 4 ]

1 голос
/ 01 ноября 2017

Если вы хотите стереть ревизию по ID, вы можете получить доступ к таблице envers напрямую, используя собственный запрос.Есть 2 таблицы, которые содержат ссылки на ревизию.Предполагая, что ваша таблица аудита использует обычный суффикс _AUD, вы можете программно найти имя таблицы сущностей.

Вот несколько фрагментов, написанных на Kotlin:

fun getAuditTableName(em: EntityManager, aClass: Class<*>): String {
    return getAuditTableName(em, aClass.name) + "_AUD"
}

fun getEntityTableName(em: EntityManager, aClass: Class<*>): String {
    val session = em.unwrap(Session::class.java) as Session
    val sessionFactory = session.sessionFactory
    val hibernateMetadata = sessionFactory.getClassMetadata(className)
    val persister = hibernateMetadata as AbstractEntityPersister
    return persister.tableName
}

Теперь, когда у нас есть имя таблицы,мы можем удалить строки в таблицах.(Поместите это в свой блок транзакции JPA, замените содержимое по мере необходимости и настройте SQL для своего провайдера).Поэтому, учитывая MyEntityClass и myRevisionId, мы можем сделать что-то вроде этого:

    val em:EntityManager = getEntityManager()
    val auditTableName = getAuditTableName(MyEntityClass::class.java)

    em.createNativeQuery("delete from `$auditTableName` where REV=${myRevisionId}").executeUpdate()
    em.createNativeQuery("delete from REVINFO where REV=${myRevisionId}").executeUpdate()

Если вы хотите удалить с помощью параметра, отличного от revisionID, просто запросите revisionIds в таблице entity_AUD, а затем удалитенайдено строк указанным способом.

Имейте в виду, что revisionId может быть связан с более чем 1 сущностью, и все записи будут удалены в предыдущем методе.Чтобы удалить ревизию для отдельной сущности, вам понадобится идентификатор сущности и ключевые имена полей сущности.

Вот код для динамического получения имени поля:

fun getEntityKeyNames(em: EntityManager, entityClass: Class<*>): List<String> {
    val session = em.unwrap(Session::class.java) as Session
    val sessionFactory = session.sessionFactory
    val hibernateMetadata = sessionFactory.getClassMetadata(entityClass.name)
    val persister = hibernateMetadata as AbstractEntityPersister
    return persister.keyColumnNames.toList()
}
1 голос
/ 11 мая 2010

Хорошо, я на 50% покончил с этим для тех, кто хочет знать.

Спасибо создателю Hibernate Envers Адаму Варски, я цитирую:

"id" - это ключевое слово hibernate для идентификатора. сущности, какими бы ни были имена; в случае объектов аудита, идентификатор составной и называется "originalId". Попробуйте:

"delete from full.package.name.User_AUD u where u.originalId.id = :userid" 

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

Если у кого-то есть подсказка, дайте мне знать.

1 голос
/ 20 апреля 2014

Это полностью работает для меня, и собственный запрос не требуется

AuditQuery aq = auditReader.createQuery()
                   .forRevisionsOfEntity( ErpEmploye.class, true, false);       
 aq.add( AuditEntity.id().eq( employe.getCodeId() ) );
 aq.add( AuditEntity.relatedId("period").eq( erpPeriod.getCodeId() ) );
 List result =  aq.getResultList();//parameters must be added, this call is required
 if (result.size()>0){
    Query query = (Query) PrivateAccessor.invokePrivateMethod( aq, "buildQuery", new Object[0]);
    String queryString = (String) PrivateAccessor.getPrivateField( query, "queryString", true );
    PrivateAccessor.setPrivateField( query, "queryString", queryString.replace("select e__ from", "delete from"), true );
    getDAO().executeQuery(query);//transaction required             
}
0 голосов
/ 08 мая 2010

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

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

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