Hibernate Envers 与 QueryDSL 更新

Yun*_*ium 2 spring hibernate querydsl hibernate-envers spring-data-jpa

Hibernate、Hibernate Envers 和 QueryDSL 在 Spring boot 中配置并正常工作1.4.1.RELEASE

问题是当使用UpdateClause<JPAUpdateClause> updateQueryBuilder = queryFactory.update(collectionTransaction);构建更新查询并执行该更新查询时,Hibernate Envers 不会拾取并审核这些更改。

以下是实现 QueryDSL 的 Spring Data JPA 存储库

public class CollectionTransactionRepositoryImpl extends QueryDslRepositorySupport implements CollectionTransactionRepositoryCustom {
    @Autowired
    private JPAQueryFactory queryFactory;

    public CollectionTransactionRepositoryImpl() {
        super(CollectionTransaction.class);
    }

    @Override
    public Collection<CollectionTransaction> updateCollectionTransaction(UpdateCollectionTransaction updateCollectionTransaction) {
        QCollectionTransaction collectionTransaction = QCollectionTransaction.collectionTransaction;
        UpdateClause<JPAUpdateClause> updateQueryBuilder = queryFactory.update(collectionTransaction);
        .....//Code omitted for brevity
        long updated = updateQueryBuilder.execute();
        //.....
        return ...
    }
}
Run Code Online (Sandbox Code Playgroud)

Hibernate Envers 有可能在这种情况下做出改变吗?

Nar*_*ros 5

这是 JIRA HHH-10318中概述的已知问题。

Envers 基于 Hibernate 的事件子系统工作,其中 Hibernate 有效地通知实体状态已以某种方式修改的各种回调,并提供先前的和新的实体状态。这种状态正是 Envers 用来确定更改内容并插入审核更改行的状态。

让我们举一个简单的例子:

UPDATE MyEntity e SET e.status = :status
Run Code Online (Sandbox Code Playgroud)

Hibernate 将执行以下任务:

  1. 刷新持久性上下文的任何修改。
  2. 使 的任何缓存实例无效MyEntity
  3. 执行批量更新操作。

在这些步骤中,Hibernate 不会加载任何现有状态。它只是保证在批量更新之前刷新当前更改,并且由于批量更新,任何后续操作都将从数据存储而不是缓存中获取。

因此,从 Envers 的角度来看,它没有得到回调,因此不知道发生了任何操作,因为 Hibernate ORM 无法为此类操作提供任何实体状态,它根本不存在。

这里最大的问题是如何(如果可能)为此类操作建模和处理变更单元。

这很困难,因为 Envers 实际上需要某种类型的 ,PreBulkOpEvent以便它可以缓存即将更改的内容,并PostBulkOpEvent要求并合并两个结果以生成更改日志条目。对这一概念的关注实际上集中在如何有效地做到这一点以避免

  1. 由于大量结果集操作导致内存不足。
  2. 从数据存储加载状态以进行大型结果集操作的执行时间较长。

不管怎样,欢迎您阅读 JIRA 并提供任何反馈或想法。但目前,它只是超出了我们目前所能捕捉到的范围。