一尘不染

扩展Hibernate Envers的实现

hibernate

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

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

ii。父maven项目的检索登录用户的实现不同。

真正的挑战实际上是实现RevisionListener。我尝试在JPA项目本身中创建一个抽象类的修订侦听器,可以在每个父Maven项目中扩展和实现它。大声笑!这没用!

无论如何,我将不胜感激。有出路吗?


阅读 330

收藏
2020-06-20

共1个答案

一尘不染

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

如果 信息
不管使用JPA的应用程序这两个应用程序的要收集有关每个版本是相同的,那么就应该在落实共同JPA项目的修订实体和监听功能没有问题。您无法执行此操作的唯一原因是,如果
信息 (即 表结构) 不同。

为此,我们需要一个抽象层。而不是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正确创建您的,并对其进行批注,包括将其指向RevisionListenerImplEnvers应该使用的侦听器实现所指向的类。

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

  1. 实施RevisionInfoProvider
  2. 填充RevisionInfoProviderHolder

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

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

父maven项目的检索登录用户的实现不同。

回到上面,正如您在上面看到的那样,带有RevisionInfoProvider句柄的抽象层可以很好地处理此问题。您为Envers建立了一个通用框架,以使其发挥作用,同时又使其具有足够的灵活性,以便每个父项目可以根据需要进行区分。

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

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

您只需要确保在检查实体的引导阶段期间可以通过JPA模块选择修订实体。

希望这可以帮助。

2020-06-20