Returning Hibernate envers Revision audit with changed flags

I am using Hibernate Envers in my application to track changes in all fields of my entities. I am using @Audited (withModifiedFlag = true) annotation for this.

The records are fixed in the database, and the _mod fields correctly indicate the changed fields.

I want to get a specific revision from some object and information about which fields have changed. For this I use the following method:

        List<Object[]> results = reader.createQuery()  
            .forRevisionsOfEntity(this.getDao().getClazz(), false, true)  
            .add(AuditEntity.id().eq(id))  
            .getResultList(); 

      

This method returns a list of an array of objects with my object as the first element.

The problem is that the returned object has no information about the changed fields. So my question is, how do I get information about the changed fields?

+3


source to share


1 answer


I know this question is a little out of date, but I tried to do this and didn't really find any answers.

There doesn't seem to be a good way to achieve this, but this is how I did it.

First, you need to use projections, which no longer give you a pretty entity model already set up for you. You will still return an array of objects, but each object in the array corresponds to each projection you added (in order).



final List<Object[]> resultList = reader.createQuery()  
        .forRevisionsOfEntity(this.getDao().getClazz(), false, true)
        // if you want revision properties like revision number/type etc
        .addProjection(AuditEntity.revisionNumber())
        // for your normal entity properties
        .addProjection(AuditEntity.id())
        .addProjection(AuditEntity.property("title")) // for each of your entity properties
        // for the modification properties
        .addProjection(new AuditProperty<Object>(new ModifiedFlagPropertyName(new EntityPropertyName("title"))))
        .add(AuditEntity.id().eq(id))
        .getResultList();

      

Then you need to map each result manually. This part is up to you, but I'm using a separate class as the revision model as it contains additional data for the normal entity data. If you wanted, you could achieve this with @Transient properties on the entity class.

final List<MyEntityRevision> results = resultList.stream().map(this::transformRevisionResult)
            .collect(Collectors.toList());


private MyEntityRevision transformRevisionResult(Object[] revisionObjects) {
    final MyEntityRevision rev = new MyEntityRevision();
    rev.setRevisionNumber((Integer) revisionObjects[0]);
    rev.setId((Long) revisionObjects[1]);
    rev.setTitle((String) revisionObjects[2]);
    rev.setTitleModified((Boolean) revisionObjects[3]);
    return rev;
}

      

+2


source







All Articles