如何从我的审核表中删除条目?
-
04-10-2019 - |
题
我目前正在与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);
}
...
}
我已经阅读了文档,论坛,很多东西,但我无法弄清楚。也许不可能,我不知道。
有人做过这个吗?
解决方案
好的,对于那些想知道的人,我已经完成了50%的工作。
感谢Hibernate Envers的创建者Adam Warski,我引用了:
“ ID”是一个冬眠的关键字,无论名称是什么,它是实体的ID;如果是审计实体,则ID为复合,称为“ OriginalID”。尝试:
"delete from full.package.name.User_AUD u where u.originalId.id = :userid"
但是现在,我也想在Revinfo表中删除与审计表相关的条目。
如果有人有任何线索,请告诉我。
其他提示
这对我来说是完全工作的,并且 无需本地查询
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
}
如果要逐一使用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()
如果您想通过除修订版以外的参数删除,只需查询entity_aud表中的修订版,然后以提及的方式删除找到的行。
请记住,修订版可能与一个以上的实体相关联,所有条目将在上一个方法中删除。要删除单个实体的修订版,您将需要该实体的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()
}
通常仅添加审核条目,即使删除了相关实体,也不会删除 思考 Envers API为此提供了支持。
现在,如果您真的想删除已删除实体的条目(这种违反了审计的目的),则可以延迟此内容,而不是在删除时间删除条目,而是每天晚上运行每天的本地查询,例如每天晚上。