在Hibernate Envers中获取以前版本的实体
我有一个由Hibernate加载的实体(通过EntityManager
):
User u = em.load(User.class, id)
该课程由Hibernate Envers审核。 如何加载以前版本的用户实体?
也许这就是(来自AuditReader文档)
AuditReader reader = AuditReaderFactory.get(entityManager); User user_rev1 = reader.find(User.class, user.getId(), 1); List revNumbers = reader.getRevisions(User.class, user_rev1); User user_previous = reader.find(User.class, user_rev1.getId(), revNumbers.get(revNumbers.size()-1));
(我对此非常新,不确定我是否拥有正确的语法,也许大小() – 1应该是size() – 2?)
这是另一个版本,它找到相对于“当前”版本号的先前版本,因此即使您正在查看的实体不是最新版本,也可以使用它。 它还处理没有事先修订的情况。 (假设em
是以前填充的EntityManager)
public static User getPreviousVersion(User user, int current_rev) { AuditReader reader = AuditReaderFactory.get(em); Number prior_revision = (Number) reader.createQuery() .forRevisionsOfEntity(User.class, false, true) .addProjection(AuditEntity.revisionNumber().max()) .add(AuditEntity.id().eq(user.getId())) .add(AuditEntity.revisionNumber().lt(current_rev)) .getSingleResult(); if (prior_revision != null) return (User) reader.find(User.class, user.getId(), prior_revision); else return null }
这可以推广到:
public static T getPreviousVersion(T entity, int current_rev) { AuditReader reader = AuditReaderFactory.get(JPA.em()); Number prior_revision = (Number) reader.createQuery() .forRevisionsOfEntity(entity.getClass(), false, true) .addProjection(AuditEntity.revisionNumber().max()) .add(AuditEntity.id().eq(((Model) entity).id)) .add(AuditEntity.revisionNumber().lt(current_rev)) .getSingleResult(); if (prior_revision != null) return (T) reader.find(entity.getClass(), ((Model) entity).id, prior_revision); else return null }
这种泛化的唯一棘手的一点是获得实体的id。 因为我正在使用Play! 框架,我可以利用所有实体都是模型并使用((Model) entity).id
获取id的事实,但你必须调整它以适应你的环境。
来自文档:
AuditReader reader = AuditReaderFactory.get(entityManager); User user_rev1 = reader.find(User.class, user.getId(), 1);
我想是这样的:
final AuditReader reader = AuditReaderFactory.get( entityManagerOrSession ); // This could probably be declared as Long instead of Object final Object pk = userCurrent.getId(); final List userRevisions = reader.getRevisions( User.class, pk ); final int revisionCount = userRevision.size(); final Number previousRevision = userRevisions.get( revisionCount - 2 ); final User userPrevious = reader.find( User.class, pk, previousRevision );
基于@ brad-mace的优秀方法,我做了以下更改:
- 你应该传入你的EntityClass和Id而不是硬编码并假设模型。
- 不要硬编码您的EntityManager。
- 没有设置selectDeleted的点,因为删除的记录永远不能作为前一版本返回。
- 如果没有找到结果或超过1个结果,则调用使用throw和exception获取单个结果,因此调用resultlist或捕获exception(此解决方案调用带有maxResults = 1的getResultList)
- 在一个事务中获取修订,类型和实体(删除投影,使用orderBy和maxResults,并查询Object [3])
所以这是另一个解决方案:
public static T getPreviousRevision(EntityManager entityManager, Class entityClass, Object entityId, int currentRev) { AuditReader reader = AuditReaderFactory.get(entityManager); List
- Spring从另一个项目导入应用程序上下文
- 用于JPA回调的Hibernate事件侦听器
- SQLGrammarException:无法执行查询
- 在Spring JSP页面中使用集合时的Hibernate LazyInitializationException
- Hibernate:org.hibernate.LazyInitializationException:无法初始化代理 – 没有会话
- 如何使用Hibernate eqOrIsNull()
- 如何在Spring Boot中使用Hibernate / JPA返回多级json
- Hibernate抛出奇怪的错误:未映射类
- 如何在不使用查询缓存的情况下缓存Spring Data JPA查询方法的结果?