Spring Data Envers:如何将修订号作为实体的一部分获取
如何让Hibernate Envers实体始终持有最新修订号
你希望在保存或查询SomeEntity实体时,实体实例中能直接包含当前最新的修订号,尝试通过在实体字段上添加@RevisionNumber注解实现,但该方式无法生效,期望实现如下代码的效果:
@Entity @Audited class SomeEntity { @Id long id; String value; @RevisionNumber int revNum; }
可行解决方案
方案1:通过Envers API手动获取并绑定最新修订号
Hibernate Envers的@RevisionNumber注解仅作用于审计实体(比如对应REVINFO表的实体),无法直接标注在业务实体字段上。你可以通过Envers提供的AuditReader工具类,手动查询指定实体的最新修订号并赋值给实体:
查询实体时同步获取修订号
当从数据库查询到SomeEntity实例后,调用API获取其最新修订版本号:
// 获取AuditReader实例 AuditReader auditReader = AuditReaderFactory.get(entityManager); // 查询指定ID实体的最新修订号 Number latestRevNum = auditReader.getLatestRevisionNumber(SomeEntity.class, entityId); // 将修订号设置到实体对象中 someEntity.setRevNum(latestRevNum.intValue());
保存实体后自动更新修订号
在实体持久化完成后,立即查询最新修订号并更新实体:
entityManager.persist(someEntity); entityManager.flush(); // 确保实体已写入数据库,生成对应的审计记录 Number latestRevNum = auditReader.getLatestRevisionNumber(SomeEntity.class, someEntity.getId()); someEntity.setRevNum(latestRevNum.intValue());
方案2:通过Hibernate事件监听器自动维护修订号
如果不想每次手动调用API,可以通过Hibernate的事件监听机制,在实体保存/更新后自动查询并设置最新修订号:
- 自定义事件监听器:
public class RevisionNumberUpdateListener implements PostInsertEventListener, PostUpdateEventListener { @Override public void onPostInsert(PostInsertEvent event) { updateRevisionNumber(event.getEntity(), event.getSession()); } @Override public void onPostUpdate(PostUpdateEvent event) { updateRevisionNumber(event.getEntity(), event.getSession()); } private void updateRevisionNumber(Object entity, Session session) { if (entity instanceof SomeEntity) { SomeEntity someEntity = (SomeEntity) entity; AuditReader auditReader = AuditReaderFactory.get(session); Number latestRevNum = auditReader.getLatestRevisionNumber(SomeEntity.class, someEntity.getId()); someEntity.setRevNum(latestRevNum.intValue()); session.merge(someEntity); } } @Override public boolean requiresPostCommitHandling(EntityPersister persister) { return false; } }
- 将监听器注册到Hibernate配置中:
在persistence.xml或Spring Boot配置类中添加该监听器,确保Hibernate在实体保存/更新时触发对应的事件逻辑。
注意事项
@RevisionNumber是Envers用于标记审计实体修订号字段的注解,无法直接映射到业务实体,Envers不会自动维护业务实体中的该字段。- 使用事件监听器时,需注意避免循环触发更新事件(比如设置
revNum后再次触发更新逻辑),可通过判断字段变更内容或添加标记位规避。
内容的提问来源于stack exchange,提问作者Oleksandr Cherniaiev
相关产品推荐
相关产品推荐

