如果您想通过 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()
}