HIbernate Envers: retrieve snapshots inserted in t

2019-08-27 21:58发布

We've got a requirement: log and persist the entity changes in the transaction in terms of diff using Hibernate Envers. We implemented a RevisionListener:

public class MyRevisionListener implements EntityTrackingRevisionListener {

    @Override
    public void newRevision(Object revision) {
        ...
    }

    @Override
    public void entityChanged(Class entityClass,
                              String entityName,
                              Serializable entityId,
                              RevisionType revisionType,
                              Object revisionEntity) {
        int revisionId = ((DefaultRevisionEntity) revisionEntity).getId();
        List<?> revisions = AuditReaderFactory.get(entityManager)
                .createQuery()
                .forRevisionsOfEntity(entityClass, false, true)
                .add(AuditEntity.id().eq(entityId))
                .add(AuditEntity.revisionNumber().le(revisionId + 1))
                .addOrder(AuditEntity.revisionNumber().desc())
                .setMaxResults(2)
                .getResultList();

        checkArgument(revisions.size() < 3, "Need at most two revisions: %s", revisions);
        checkArgument(revisions.size() > 0, "Need at least one revision: %s", revisions);

        // continue with diff calculation;
    }

}

Questions:
1. First assertion: Do I need this checking? Having the above query Is it possible that the result contains more than two items?
2. Second assertion: I assume for every change (INSERT/UPDATE/DELETE) there's at least one snapshot (or revision). Is that right? If so why do my test cases (with an UPDATE operation) fail randomly due to this assertion failure (meaning there's no snapshot).

Please let me know if I need to provide more information.

UPDATE
The problem was with Spring Test, context, and bean management (specifically how I obtain EntityManager). I accepted the post by @Naros as it answered the first question and gave a hit for the second question :)

1条回答
何必那么认真
2楼-- · 2019-08-27 22:49

Do I need this checking? Having the above query Is it possible that the result contains more than two items?

No, setMaxResults(2) will guarantee that the query returns only a maximum of 2 rows; however you'll need to handle the use case where the query returns less-than 2.

I assume for every change (INSERT/UPDATE/DELETE) there's at least one snapshot (or revision). Is that right? If so why do my test cases (with an UPDATE operation) fail randomly due to this assertion failure (meaning there's no snapshot).

I wouldn't expect your test case to fail randomly unless you're doing something you shouldn't be. The audit process with Envers is pretty deterministic, so I would expect it to either fail or succeed consistently.

As to why you aren't getting the expected number of rows, my guess would be either some flush mode configuration is at play that could interfere with Envers audit queries or perhaps you're querying the audit schema amidst saving an entity and its associations such that an expected valid predicate where clause is invalid at that precise moment?

Without seeing your test case, I can only speculate for the most part. If you can post your test case and entity mappings, I could dig a bit deeper.

查看更多
登录 后发表回答