2016-03-15 15 views
5

Sto usando spring-data-envers nella mia applicazione di avvio a molla. Posso registrare correttamente gli audit sulle mie entità.Come trovare tutte le revisioni per un'entità utilizzando i dati di inversione di primavera?

Ora, ho bisogno di mostrare i dati controllati all'utente nell'interfaccia utente. Come se ci fosse un modulo di ricerca in cui l'utente può selezionare la durata e l'entità per cui desidera vedere i registri di controllo.

RevisionRepository fornito da string-data-envers ha solo tre metodi come segue.

@NoRepositoryBean 
public interface RevisionRepository<T, ID extends Serializable, N extends Number & Comparable<N>> { 

    /** 
    * Returns the revision of the entity it was last changed in. 
    * 
    * @param id must not be {@literal null}. 
    * @return 
    */ 
    Revision<N, T> findLastChangeRevision(ID id); 

    /** 
    * Returns all {@link Revisions} of an entity with the given id. 
    * 
    * @param id must not be {@literal null}. 
    * @return 
    */ 
    Revisions<N, T> findRevisions(ID id); 

    /** 
    * Returns a {@link Page} of revisions for the entity with the given id. 
    * 
    * @param id must not be {@literal null}. 
    * @param pageable 
    * @return 
    */ 
    Page<Revision<N, T>> findRevisions(ID id, Pageable pageable); 
} 

Come si scrive una query personalizzata per ottenere tutte le revisioni di un'entità tra due date da un determinato utente.

Si noti che, ho aggiunto ulteriori colonne alla tabella user_rev_entity in cui memorizzo ID utente e data di modifica. Se mi unisco a questa tabella con la tabella entity_aud, posso ottenere i risultati.

Di seguito sono riportati gli script delle tabelle di controllo.

CREATE TABLE `user_rev_entity` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `timestamp` bigint(20) NOT NULL, 
    `created_by` bigint(20) NOT NULL, 
    `created_date` datetime NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 

CREATE TABLE `revchanges` (
    `rev` int(11) NOT NULL, 
    `entityname` varchar(255) DEFAULT NULL, 
    KEY `FK_et6b2lrkqkab5mhvxkv861n8h` (`rev`), 
    CONSTRAINT `FK_et6b2lrkqkab5mhvxkv861n8h` FOREIGN KEY (`rev`) REFERENCES `user_rev_entity` (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 

CREATE TABLE `roles_aud` (
    `role_id` bigint(20) NOT NULL, 
    `rev` int(11) NOT NULL, 
    `revtype` tinyint(4) DEFAULT NULL, 
    `description` varchar(255) DEFAULT NULL, 
    `description_mod` bit(1) DEFAULT NULL, 
    `display_name` varchar(255) DEFAULT NULL, 
    `display_name_mod` bit(1) DEFAULT NULL, 
    `is_enabled` bit(1) DEFAULT NULL, 
    `enabled_mod` bit(1) DEFAULT NULL, 
    `title` varchar(255) DEFAULT NULL, 
    `title_mod` bit(1) DEFAULT NULL, 
    PRIMARY KEY (`role_id`,`rev`), 
    KEY `FK_pkqm51vsc35w2axvnns4bpas9` (`rev`), 
    CONSTRAINT `FK_pkqm51vsc35w2axvnns4bpas9` FOREIGN KEY (`rev`) REFERENCES `user_rev_entity` (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 

Quindi, in sostanza sto cercando tutte le modifiche apportate da un particolare utente durante un determinato periodo di tempo per un'entità dire Ruolo.

Ci saranno molte più tali entità.

risposta

1

Spring Data Envers non supporta query personalizzate come si è abituati in primavera dati jpa. Tutto ciò che fa è fornire la comoda interfaccia RevisionRepository.

Tuttavia, ciò che si può fare è utilizzare il metodo Revisions<N, T> findRevisions(ID id) e applicare un filtro dal proprio livello di servizio. Ecco un esempio.

@Service 
public UserService { 
    @Resource 
    private UserRepository userRepository; 

    public List<Revision<Integer, User>> findRevisionsBetweenDates(int id, Date startDate, Date endDate){ 
     return userRepository.findRevisions(id).getContent().stream().filter(
      revision -> revision.getEntity().getCreatedDate().getTime() > startDate.getTime() && 
       revision.getEntity().getCreatedDate().getTime() < endDate.getTime() 
     ).collect(Collectors.toList()); 
} 

Non si adatta perfettamente poiché si recuperano tutte le revisioni dal database. Tuttavia, è il modo più semplice per mantenere un'astrazione dal database.

In caso contrario, saltare Spring Data Envers e lavorare con Envers API.

Buona fortuna, saluti

+0

* Non una misura perfetta dal momento che si prendere tutte le revisioni dal database *. Suppongo che tu possa dire che due volte, la tabella della storia dovrebbe essere la più pesante in un database, questo è sicuramente qui che non vuoi post-filtro. – Walfrat

1

Hai guardato AuditReaderFactory e AuditReader?

Partenza la documentazione per AuditReader di createQuery:

Un creatore di query, associato a questa istanza AuditReader, con la quale è possibile creare query e successivamente giustiziati.

che restituisce un AuditQueryCreator che può essere utilizzato per creare una query in questo modo:

AuditQuery query = getAuditReader().createQuery() 
.forRevisionsOfEntity(MyEntity.class, false, true); 

Ci sono un paio di opzioni per forRevisionsOfEntity, consultare la documentazione AuditQueryCreator.

La query dovrebbe consentire di selezionare revisioni specifiche utilizzando AuditCriterion

Hibernate documentazione envers relativa al presente: http://docs.jboss.org/hibernate/orm/5.0/userGuide/en-US/html_single/#revisions-of-entity

È possibile aggiungere vincoli a questa query nello stesso modo in cui al precedente . Ci sono alcune possibilità aggiuntive:

  1. utilizzando AuditEntity.revisionNumber() è possibile specificare vincoli, proiezioni e ordine sul numero di revisione, in cui il controllato entità è stata modificata
  2. Allo stesso modo, utilizzando AuditEntity.revisionProperty (propertyName) è possibile specificare vincoli, proiezioni e ordine su una proprietà dell'ente di revisione , corrispondente alla revisione in cui l'ente sottoposto a revisione è stato modificato
  3. AuditEntity.revisionType() consente l'accesso come sopra a il tipo di revisione (ADD, MOD, DEL).

EDIT ho dato un colpo ad una soluzione vera e propria. Ho poca envers e ibernazione dei criteri di esperienza, quindi questo potrebbe non essere giusto, ma forse ti aiuterà a iniziare.

AuditQuery query = getAuditReader().createQuery() 
     .forRevisionsOfEntity(MyEntity.class, false, true); 

query.add(AuditEntity.revisionProperty("createdDate").gt(minDate)) 
     .add(AuditEntity.revisionProperty("createdDate").lt(maxDate)) 
     .add(AuditEntity.revisionProperty("createdBy").eq(userId)); 

//the documentation shows getSingleResult returns a number 
//so i'm guessing a resultList also contains numbers 
List<Number> resultList = query.getResultList(); 
1

più Un problema è, il metodo findRevisions utilizza internamente SQL clausola, che falliranno se i record sono più di 999.

Problemi correlati