Domanda

Al momento sto lavorando con Hibernate Envers.

Come eliminare le voci nella tabella di audit relativo all'entità voglio cancellare? Il mio soggetto non ha alcuna relazione con altre entità.

Ho capito che devo farlo in modo onPostDelete della mia listener personalizzato:

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);
  }
  ...

}

Ho letto la documentazione, forum, molte cose, ma non riesco a capirlo. Forse non è possibile, non lo so.

Qualcuno ha mai fatto prima?

È stato utile?

Soluzione

Ok io sono il 50% fatto con questo per coloro che vogliono sapere.

Grazie al creatore di Hibernate Envers, Adam Warski, cito:

  

"id" è una parola chiave di sospensione per l'id   di un'entità, qualunque sia il nome sia;   in caso di enti di revisione contabile, l'id è   composito e si chiama "originalId".   Prova:

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

Ma ora, mi piacerebbe anche eliminare le voci relative alla tabella di controllo nel mio tavolo revinfo.

Se qualcuno ha un indizio, fatemelo sapere.

Altri suggerimenti

Questo è completamente funzionante per me, e nessuna query nativa richiesta

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             
}

Se si vuole eliminare una revisione per ID, è possibile accedere alla tabella envers direttamente utilizzando una query nativo. Ci sono 2 tavoli che contengono riferimenti alla revisione. Assumendo che il tabella di controllo utilizza il suffisso _AUD convenzionale, è possibile trovare il nome della tabella entità di programmazione.

Ecco alcuni frammenti scritti in 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
}

Ora che abbiamo il nome della tabella, si può rimuovere le righe nelle tabelle. (Mettete questo nella vostra blocco di transazione JPA, sostituire il contenuto, se necessario, e regolare l'SQL per il vostro provider). Quindi, dato MyEntityClass e myRevisionId, siamo in grado di fare qualcosa di simile:

    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()

Se si desidera eliminare da un parametro diverso da quello RevisionId, semplicemente query per le le revisionIds nella tabella entity_AUD, e quindi eliminare le righe trovate nel modo indicato.

tenere presente che un RevisionId può essere associato a più di 1 soggetto, e tutte le voci verrà rimosso nel metodo precedente. Per eliminare la revisione per una sola entità, è necessario l'ID del soggetto e il nome campo chiave di entità (s).

Ecco il codice per ottenere in modo dinamico il nome del campo:

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()
}

voci di controllo vengono tipicamente aggiunti solo, non eliminati, anche quando l'ente collegato viene eliminato in modo non mi pensare che i Envers API forniscono il supporto per questo.

Ora, se davvero si desidera rimuovere le voci per le entità eliminate (questa sconfigge un pò lo scopo di auditing), si può forse ritardare questo un po 'e invece di rimuovere le voci in fase di cancellazione, eseguire una query nativo quotidiana, ad esempio ogni notte.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top