如何从我的审核表中删除条目?

发布于 2024-08-31 08:51:58 字数 785 浏览 6 评论 0原文

我目前正在与 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);
  }
  ...

}

我已经阅读了文档、论坛等很多内容,但我无法弄清楚。也许这是不可能的,我不知道。

以前有人这样做过吗?

I am currently working with Hibernate Envers.

How to delete entries in the audit table related to the entity I want to delete? My entity has no relation with other entities.

I figured out that I have to do that in 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've read the documentation, forums, many things but I can't figure it out. Maybe it's not possible, I don't know.

Has someone ever done this before?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

痴梦一场 2024-09-07 08:51:58

好吧,对于那些想知道的人来说,我已经完成了 50%。

感谢 Hibernate Envers 的创建者 Adam Warski,我引用:

“id”是 id 的 hibernate 关键字
一个实体的名称,无论其名称是什么;
对于审计实体,id 是
复合并称为“originalId”。
尝试:

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

但是现在,我还想删除 revinfo 表中与审计表相关的条目。

如果有人有线索,请告诉我。

Ok I'm 50% done with this for those who want to know.

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

"id" is a hibernate keyword for the id
of an entity, whatever the names is;
in case of audit entities, the id is
composite and is called "originalId".
Try:

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

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

If someone has a clue, let me know.

烟织青萝梦 2024-09-07 08:51:58

这对我来说完全有效,并且不需要本机查询

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             
}

This is fully working to me, and no native query required

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             
}
风轻花落早 2024-09-07 08:51:58

如果您想按 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 以外的参数进行删除,只需在entity_AUD 表中查询 revisionIds,然后按照上述方式删除找到的行即可。

请记住,一个 revisionId 可能与多个实体关联,并且所有条目都将在上一个方法中删除。要删除单个实体的修订,您将需要实体的 ID 和实体的关键字段名称。

下面是动态获取字段名称的代码:

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

If you want to wipe out a revision by ID, you can access the envers table directly using a native query. There are 2 tables that contain references to the revision. Assuming your audit table uses the conventional _AUD suffix, you can find the entity table name programmatically.

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 remove the rows in the tables. (Put this in your JPA transaction block, replace the content as needed, and adjust the SQL for your provider). So 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 delete by a parameter other than the revisionID, simply query for the the revisionIds in the entity_AUD table, and then delete the found rows in the mentioned way.

Keep in mind that a revisionId may be associated with more than 1 entity, and all of the entries will be removed in the previous method. To delete the revision for a single entity, you will need the entity's ID and entity's key field name(s).

Here is 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()
}
不醒的梦 2024-09-07 08:51:58

审核条目通常只会添加,不会删除,即使相关实体已删除,因此我不认为 Envers API 对此提供支持。

现在,如果您确实想删除已删除实体的条目(这有点违背了审核的目的),您可以稍微延迟一下,而不是在删除时删除条目,而是运行每日本机查询,例如每天晚上。

Audit entries are typically only added, not deleted, even when the related entity is deleted so I don't think that the Envers API provide support for that.

Now, if really you want to remove entries for deleted entities (this kinda defeats the purpose of auditing), you can maybe delay this a bit and instead of removing entries at deletion time, run a daily native query, for example every night.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文