如何不使用原生查询删除Hibernate Envers中3个月以上的审计历史
删除Hibernate Envers旧审计数据(非原生查询方式)
要清理距今3个月以上的审计数据且不使用原生SQL,核心思路是先定位过期的修订记录,再关联删除对应审计表数据,具体步骤如下:
1. 获取AuditReader实例
通过EntityManager获取Envers的AuditReader,用于查询修订信息:
AuditReader auditReader = AuditReaderFactory.get(entityManager);
2. 计算时间阈值
算出3个月前的毫秒级时间戳,作为筛选过期修订的条件:
LocalDate threeMonthsAgo = LocalDate.now().minusMonths(3); Instant cutoffInstant = threeMonthsAgo.atStartOfDay(ZoneId.systemDefault()).toInstant(); long cutoffTimestamp = cutoffInstant.toEpochMilli();
3. 查询过期的修订ID
从默认的REVINFO表(对应实体DefaultRevisionEntity)中筛选出时间早于阈值的修订ID列表:
List<Number> oldRevIds = auditReader.createQuery() .forEntitiesAtRevision(DefaultRevisionEntity.class, Number.class) .add(AuditEntity.revisionProperty("timestamp").lt(cutoffTimestamp)) .getResultList();
4. 删除审计表中的关联数据
针对每个实体的审计表(比如你提到的Entity_History),用JPQL删除关联这些过期修订ID的记录。必须先处理所有审计表,再删除REVINFO记录,避免外键约束报错:
// 示例:删除Entity_History表中的过期审计数据 String deleteAuditJpql = "DELETE FROM Entity_History e WHERE e.rev IN :oldRevIds"; entityManager.createQuery(deleteAuditJpql) .setParameter("oldRevIds", oldRevIds) .executeUpdate(); // 如有多个实体的审计表,重复上述操作即可
5. 删除REVINFO中的过期修订记录
最后清理REVINFO表中对应的旧记录:
String deleteRevJpql = "DELETE FROM DefaultRevisionEntity r WHERE r.id IN :oldRevIds"; entityManager.createQuery(deleteRevJpql) .setParameter("oldRevIds", oldRevIds) .executeUpdate();
注意事项
- 所有操作需在同一个事务中执行,保证数据一致性。
- 若审计表为自定义命名,需确保JPQL中使用的实体类名称与Envers生成的审计实体(或你自定义的审计实体类)对应。
- 批量删除前建议备份数据,避免误删。
内容的提问来源于stack exchange,提问作者L. Tudy
相关产品推荐
相关产品推荐

