fuqsha
fuqsha

Reputation: 73

Hibernate Envers - how to map custom RevisionEntity columns into audit queries

I have separated the auditing support and the revisions in my solution. It works fine, but I have no idea how to create a query to get all revisions where the audit data is mapped from the REVINFO to the MyEntity in the query result. Like joining the MYENTITY_AUD and the REVINFO on REV for lastModified columns. For created columns it is even more complicated, because it might requires a subquery with REVTYPE = 0.

private List<MyEntity> allRevisions() {
  AuditReaderFactory.get(entityManager).createQuery()
    .forRevisionsOfEntity(MyEntity.class, true, true)        
    .addOrder(AuditEntity.revisionNumber().asc())
    .getResultList();
}

My tables looks like this:

MYENTITY table
+---------------------------------------------------------------------------+
| ID | MYDATA | CREATEDBY | CREATEDDATE | LASTMODIFIEDBY | LASTMODIFIEDDATE |
+---------------------------------------------------------------------------+

MYENTITY_AUD table
+-----------------------------+
| ID | REV | REVTYPE | MYDATA |
+-----------------------------+

REVINFO table
+-----------------------------+
| REV | REVTSTMP | MODIFIEDBY |
+-----------------------------+

Examples from the code:

@Audited
@Entity
public class MyEntity {
    
    private String myData;

    @CreatedBy
    @NotAudited
    private String createBy;

    @CreateDate
    @NotAudited
    private LocalDateTime createdDate;

    @LastModifiedBy
    @NotAudited
    private String lastModifiedBy;

    @LastModifiedDate
    @NotAudited
    private LocalDateTime lastModifiedDate;
}

@Entity
@Table(name = "REVINFO")
@RevisionEntity(MyRevisionListener.class)
public class MyRevisionEntity implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @RevisionNumber
    @Column(name = "REV")
    private int id;

    @RevisionTimestamp
    @Column(name = "REVTSTMP")
    private long timestamp;

    @Column(name = "MODIFIED_BY")
    private String modifiedBy;
    ...
}
public class MyRevisionListener implements RevisionListener {

    @Override
    public void newRevision(Object revisionEntity) {
        MyRevisionEntity revision = (MyRevisionEntity) revisionEntity;
        revision.setModifiedBy(MyContext.getUserName())
    }
}

Thanks.

Upvotes: 0

Views: 82

Answers (1)

Thorben Janssen
Thorben Janssen

Reputation: 3275

I'm not sure if I understand your question correctly because you already seem to have everything you need.

Based on your MyRevisionEntity and MyRevisionListener implementation, Envers uses your MyRevisionEntity as the revision.

If you want to get the revision information in your allRevisions method, you only have to set the 1st boolean provided to the forRevisionsOfEntity method to false. The query then returns a List<Object[]> with MyEntity and MyRevisionEntity.

private List<Object[]> allRevisions() {
  AuditReaderFactory.get(entityManager).createQuery()
    .forRevisionsOfEntity(MyEntity.class, false, true)        
    .addOrder(AuditEntity.revisionNumber().asc())
    .getResultList();
}

Upvotes: 0

Related Questions