Domanda

Ho un'entità caricato da Hibernate (via EntityManager):

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

Questa classe è controllata da Hibernate Envers. Come posso caricare la versione precedente di un entità User?

È stato utile?

Soluzione

forse questo allora (da AuditReader docs)

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));

(Sono molto nuovo a questo, non so se ho tutto il diritto di sintassi, forse la dimensione () - 1 dovrebbe essere formato () - 2?)

Altri suggerimenti

Ecco un'altra versione che trova alla precedente revisione relativa ad un numero di revisione "corrente", in modo che possa essere utilizzato anche se l'entità si sta guardando non è l'ultima revisione. Gestisce anche il caso in cui vi non è di una revisione precedente. (em viene considerato un EntityManager precedentemente occupato)

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
}

Questo può essere generalizzato a:

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
}

L'unica po 'complicato con questa generalizzazione è sempre id dell'entità. Perché sto dalla Play! quadro, posso sfruttare il fatto che tutte le entità sono modelli e utilizzare ((Model) entity).id per ottenere l'id, ma dovrete regolare questo per soddisfare il vostro ambiente.

penso che sarebbe questo:

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 );

Dalla documentazione:

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

Costruzione off del ottimo approccio di @ brad-mazza, ho apportato le seguenti modifiche:

  • Si dovrebbe passare nella tua EntityClass e Id al posto di hardcoding e assumendo il modello.
  • Non hardcode tuo EntityManager.
  • Non v'è alcuna impostazione selectDeleted punto, perché un record eliminato non può mai essere restituito come alla revisione precedente.
  • Calling ottenere singolo risultato con un tiro e l'eccezione, se non ha prodotto risultati o di più di 1 risultato è trovato, quindi o chiamare risultante o intercettare l'eccezione (questa soluzione richiede getResultList con maxResults = 1)
  • Ottenere la revisione, il tipo e l'entità in una transazione (rimuovere la proiezione, utilizzare orderBy e maxResults, e query per l'oggetto [3])

Quindi, ecco un'altra soluzione:

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];
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top