扩展 Hibernate Envers 实现

Extending Hibernate Envers Implementation

我有 2 个 Maven 项目,它们在各自的 POM 中共享一个 JPA 项目作为依赖项。 JPA 项目是 ver 2.1 并且已经成功实现了 hibernate envers。 但是我现在需要创建一个自定义的 RevisionEntity,因为我需要审核额外的属性,例如登录的用户 ID。问题是:

我。我不能直接在 JPA 项目中实现它

二。检索已登录用户的实现因父 Maven 项目而异。

真正的挑战实际上是实现 RevisionListener。我尝试在 JPA 项目本身中创建一个抽象 class revisionlistener,我可以在每个父 maven 项目中扩展和实现它。哈哈!这没有用!

如果能帮助我度过难关,我将不胜感激。有出路吗?

I cant implement this directly in the JPA project

如果您要收集的有关每个修订的信息 是相同的,而不管使用您的 JPA 应用程序的两个应用程序如何,那么实施修订实体和侦听器应该没有问题公共 JPA 项目中的功能。您无法执行此操作的唯一原因是 信息 ,换句话说 table 结构 不同。

为此,我们需要一个抽象层。而不是像您尝试的那样扩展 RevisionListener,您将拥有另一个表示 服务的接口 侦听器将需要然后在您的子项目中实现该服务。

/**
 * Interface that implementations should extend to provider revision
 * information to the Envers revision listener.
 */
public interface RevisionInfoProvider {
  String getUserName();
}

/**
 * A class that holds a RevisionInfoProvider as a ThreadLocal.
 */
public class RevisionInfoProviderHolder {
   public static RevisionInfoProvider getProvider() {
     // impl details here to get a RevisionInfoProvider.
   }
}

那么您的修订侦听器实现可能类似于以下内容:

public class RevisionListenerImpl implements RevisionListener {
  @Override
  public void newRevision(Object revisionEntity) {
    if ( CustomRevisionEntity.class.isInstance( revisionEntity ) ) {
      CustomRevisionEntity entity = (CustomRevisionEntity) revisionEntity;
      // get provider from thread local and set user details
      RevisionInfoProvider provider = RevisionInfoProviderHolder.getProvider();
      entity.setUserName( provider.getUserName() );          
    }
    // todo: may want to assert in case you change entity types?
  }
}

此时,只需创建您的 CustomRevisionEntity,正确注释它,包括将其指向 RevisionListenerImpl class 作为 Envers 应该使用的侦听器实现。

现在在你的每个子项目中,你需要做的就是:

  1. 实施 RevisionInfoProvider
  2. 填充 RevisionInfoProviderHolder

第一个只是 JPA 项目如何从每个子项目获取详细信息的网关。例如,在 spring 网络应用程序中,这可能只是一些 spring 服务 bean。

第二个是每个线程在调用任何 JPA 内容之前需要做的事情。同样在 spring Web 应用程序中,这可能是某种类型的 Web 过滤器,它在调用用户代码之前在过滤器链的顶部执行,以确保正确设置 ThreadLocal。

The implementation for retrieving the logged in user differs for the parent maven projects.

回到这一点,正如您在上面看到的,带有 RevisionInfoProvider 的抽象层很好地处理了这个问题。您为 Envers 构建了一个通用框架来完成它的工作,同时让它足够灵活,以便每个父项目都可以根据需要分开。

如果每个父项目存储不同的结构化信息怎么办?

如果您确实遇到这种情况,则需要在每个父项目中分别实现修订实体和侦听器按照我上面提到的,但使用满足 both 父模块要求的修订实体。

您只需要确保修订实体可以在检查实体的 bootstrap 阶段被 JPA 模块拾取。

希望对您有所帮助。