簡體   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