How to delete records from my audit table?

I am currently working with Hibernate Envers.

How to delete entries in the audit table associated with the object I want to delete? My essence is not related to other objects.

I realized that I had to do this in the onPostDelete method of my custom listener:

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

I read the documentation, forums, a lot, but I can not understand. Perhaps this is impossible, I do not know.

Has anyone ever done this before?

+4
source share
4 answers

Good. I did it 50% for those who want to know.

Thanks to the creator of Hibernate Envers, Adam Warski, I quote:

"id" is the hibernate keyword for an entity identifier, regardless of name; in the case of audit firms, the identifier is composite and is called "originalId". Try:

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

But now, I would also like to delete the entries related to the audit table in my revinfo table.

If anyone has a key, let me know.

+1
source

This works completely for me, not requiring my own request

 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 } 
+1
source

If you want to destroy the revision by identifier, you can access the envers table directly using your own query. There are two tables containing links to the revision. Assuming your audit table uses the usual _AUD suffix, you can programmatically determine the name of the entity table.

Here are some snippets written 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 } 

Now that we have the table name, we can delete the rows in the tables. (Put this in the JPA transaction block, replace the content as needed, and configure SQL for your provider). Therefore, given MyEntityClass and myRevisionId, we can do something like this:

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

If you want to remove a parameter other than the revisionID, just query the revisionIds parameters in the entity_AUD table, and then delete the found rows in the specified way.

Keep in mind that the versionId file can be associated with more than 1 entity, and all entries will be deleted in the previous method. To remove a revision for a single object, you will need the names and identifiers of the name of the entity and entity.

Here is the code for dynamically getting the field name:

 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
source

Audit entries are usually added, not deleted, even if the related object is deleted, so I don't think the Envers API provides support for this.

Now, if you really want to delete records for deleted objects (this type defeats the purpose of the audit), you can delay this for a while, and instead of deleting records during deletion, run your own daily request, for example, every night.

0
source

Source: https://habr.com/ru/post/1309144/


All Articles