【问题标题】:HIbernate Envers: retrieve snapshots inserted in the same transactionHIbernate Envers:检索插入在同一事务中的快照
【发布时间】:2018-06-06 17:07:42
【问题描述】:

我们有一个要求:使用 Hibernate Envers 根据差异记录和持久化事务中的实体更改。我们实现了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;
    }

}

问题:
1. 第一个断言:我需要这个检查吗?有上述查询结果是否有可能包含两个以上的项目?
2. 第二个断言:我假设每次更改(INSERT/UPDATE/DELETE)至少有一个快照(或修订)。那正确吗?如果是这样,为什么我的测试用例(使用 UPDATE 操作)会因为断言失败(意味着没有快照)而随机失败。

如果我需要提供更多信息,请告诉我。

更新
问题在于 Spring 测试、上下文和 bean 管理(特别是我如何获得EntityManager)。我接受了@Naros 的帖子,因为它回答了第一个问题并回答了第二个问题:)

【问题讨论】:

  • 是否有任何特殊原因您不能在查询时使用 AuditReader API 来执行此操作?我担心您可能会在并发场景中遇到问题,其中 2 个会话背靠背修改同一个条目,您最终可能会在事务提交时错误地生成差异。
  • 查询时间是什么意思?我不知道该怎么做。有什么例子或指南吗?谢谢
  • 让我问一下,您是否需要仅在 UI 中显示此 diff 或根据需要报告您可以访问 Envers API 的情况?我不想建议您打算直接从数据库访问它的解决方案。
  • 我需要将差异作为事务的一部分进行持久化。
  • 首先,Envers 允许您在 @Audited 注释上使用 withModifiedFlag=true 选项来执行此操作。同样,我认为您不需要在此处编写任何自定义内容,而是在需要差异时使用 AuditReader API 来获取它。你没有给我任何真正可以继续下去的东西。

标签: hibernate hibernate-envers


【解决方案1】:

我需要这个检查吗?有上面的查询,结果是否有可能包含两个以上的项目?

不,setMaxResults(2) 将保证查询最多只返回 2 行;但是您需要处理查询返回小于 2 的用例。

我假设每次更改(插入/更新/删除)都至少有一个快照(或修订)。那正确吗?如果是这样,为什么我的测试用例(使用 UPDATE 操作)会因为断言失败(意味着没有快照)而随机失败。

我不希望您的测试用例随机失败,除非您正在做不应该做的事情。 Envers 的审计过程非常具有确定性,因此我预计它要么失败要么持续成功。

至于为什么您没有获得预期的行数,我的猜测可能是某些刷新模式配置正在发挥作用,可能会干扰 Envers 审计查询,或者您可能在保存实体和它的关联使得预期的有效谓词 where 子句在那个精确时刻无效?

没有看到你的测试用例,我只能推测大部分。如果您可以发布您的测试用例和实体映射,我可以更深入地挖掘。

【讨论】:

  • 非常感谢您的回答。它帮助我弄清楚了问题所在。事实上,问题不在于这部分代码,而在于 Spring Test、上下文和 bean 管理。
猜你喜欢
  • 2011-07-13
  • 2016-04-30
  • 2016-12-14
  • 1970-01-01
  • 2013-08-20
  • 2017-10-09
  • 1970-01-01
  • 2013-07-29
  • 2018-02-25
相关资源
最近更新 更多