Java 获取Hibernate Envers中实体的早期版本

Java 获取Hibernate Envers中实体的早期版本,java,hibernate,jboss,hibernate-envers,Java,Hibernate,Jboss,Hibernate Envers,我有一个由Hibernate加载的实体(通过EntityManager): 此类由Hibernate Envers审核。如何加载用户实体的早期版本?来自文档: AuditReader reader = AuditReaderFactory.get(entityManager); User user_rev1 = reader.find(User.class, user.getId(), 1); 也许是这样(来自文档) AuditReader=AuditReaderFactory.get(ent

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

此类由Hibernate Envers审核。如何加载用户实体的早期版本?

来自文档:

AuditReader reader = AuditReaderFactory.get(entityManager);
User user_rev1 = reader.find(User.class, user.getId(), 1);
也许是这样(来自文档)

AuditReader=AuditReaderFactory.get(entityManager);
User User\u rev1=reader.find(User.class,User.getId(),1);
List revNumbers=reader.getRevisions(User.class,User\u rev1);
User User\u previous=reader.find(User.class,User\u rev1.getId(),
获取(revNumbers.size()-1));

(我对此非常陌生,不确定是否所有语法都正确,也许size()-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 );
final AuditReader=AuditReaderFactory.get(EntityManagerSession);
//这可能被声明为Long而不是Object
最终对象pk=userCurrent.getId();
最终列表userRevisions=reader.getRevisions(User.class,pk);
final int-revisionCount=userRevision.size();
最终编号previousRevision=userRevisions.get(revisionCount-2);
最终用户userPrevious=reader.find(User.class,pk,previousRevision);

这是另一个版本,它可以查找与“当前”版本号相关的先前版本,因此即使您查看的实体不是最新版本,也可以使用它。它还处理没有先前版本的情况。(
em
假定为先前填充的EntityManager)

这可以概括为:

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。因为我正在使用游戏!框架中,我可以利用所有实体都是模型这一事实,并使用
((Model)entity).id
获取id,但您必须调整它以适应您的环境。

基于@brad mace的优秀方法,我做了以下更改:

  • 您应该传入EntityClass和Id,而不是硬编码和假设模型
  • 不要硬编码您的EntityManager
  • 没有点设置selectDeleted,因为删除的记录永远不能作为上一版本返回
  • 如果未找到任何结果或找到多个结果,则调用get single result with throw and exception,因此可以调用resultlist或捕获异常(此解决方案使用maxResults=1调用getResultList)
  • 在一个事务中获取修订、类型和实体(删除投影,使用orderBy和maxResults,并查询对象[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];
}
public static T getPreviousRevision(EntityManager EntityManager,类entityClass,对象entityId,int currentRev){
AuditReader=AuditReaderFactory.get(entityManager);
List priorRevisions=(List)reader.createQuery()
.用于修改实体(实体类、假、假)
.add(AuditEntity.id().eq(entityId))
.add(AuditEntity.revisionNumber().lt(currentRev))
.addOrder(AuditEntity.revisionNumber().desc())
.setMaxResults(1)
.getResultList();
if(priorRevisions.size()=0){
返回null;
}
//该列表包含一个具有实体、revinfo和类型的对象[]
return(T)priorRevision.get(0)[0];
}

我不确定这是否适用于我的,我想得到以前的版本,您的示例得到一个强制版本(在本例中,版本号为1)。它确实需要
size()-2
才能得到第二个到最后一个版本为什么有
user\u rev1
reader.getRevisions
接受primaryKey作为第二个参数。不是实体。因此,您只需要
AuditReader=AuditReaderFactory.get(entityManager);List revNumbers=reader.getRevisions(User.class,User.getId());User User_previous=reader.find(User.class,User.getId(),revNumbers.get(revNumbers.size()-1))
不会
for RevisionSofEntity(clazz,false,true)
返回带有实例、修订信息和修订类型的
对象[]
?如何将其类型转换为
编号
?addProjection将其更改为返回修订号,是否有方法让其直接返回实体?(而不是在之后再次运行查找)
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
}
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];
}