繁体   English   中英

在Hibernate Envers中获取以前版本的实体

[英]Get previous version of entity in Hibernate Envers

我有一个由Hibernate加载的实体(通过EntityManager ):

User u = em.load(User.class, id)

该课程由Hibernate Envers审核。 如何加载以前版本的用户实体?

这是另一个版本,它找到相对于“当前”版本号的先前版本,因此即使您正在查看的实体不是最新版本,也可以使用它。 它还处理没有事先修订的情况。 (假设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文档)

AuditReader reader = AuditReaderFactory.get(entityManager);
User user_rev1 = reader.find(User.class, user.getId(), 1);

List<Number> 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?)

我想是这样的:

final AuditReader reader = AuditReaderFactory.get( entityManagerOrSession );

// This could probably be declared as Long instead of Object
final Object pk = userCurrent.getId();

final List<Number> 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或捕获异常(此解决方案调用getResultList with maxResults = 1)
  • 在一个事务中获取修订,类型和实体(删除投影,使用orderBy和maxResults,并查询Object [3])

所以这是另一个解决方案:

public static <T> T getPreviousRevision(EntityManager entityManager, Class<T> entityClass, Object entityId, int currentRev) {
    AuditReader reader = AuditReaderFactory.get(entityManager);
    List<Object[]> priorRevisions = (List<Object[]>) reader.createQuery()
            .forRevisionsOfEntity(entityClass, false, false)
            .add(AuditEntity.id().eq(entityId))
            .add(AuditEntity.revisionNumber().lt(currentRev))
            .addOrder(AuditEntity.revisionNumber().desc())
            .setMaxResults(1)
            .getResultList();

    if (priorRevisions.size() == 0) {
        return null;
    }
    // The list contains a single Object[] with entity, revinfo, and type 
    return (T) priorRevision.get(0)[0];
}

来自文档:

AuditReader reader = AuditReaderFactory.get(entityManager);
User user_rev1 = reader.find(User.class, user.getId(), 1);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM