我有2个maven项目,它们共享一个JPA项目,作为其各个POM中的依赖项。 JPA项目是在2.1版本上,并成功实现了hibernate envers。 但是我现在需要创建一个自定义的RevisionEntity,因为我需要审计额外的属性,例如登录的用户ID。问题是:
我。我无法直接在JPA项目中实现它
II。检索登录用户的实现因父母maven项目而异。
真正的挑战实际上是实现RevisionListener。我尝试在JPA项目本身中创建一个抽象类revisionlistener,我可以在每个父maven项目中扩展和实现它。大声笑!这没有用!
我将不胜感激任何让我了解这一点的帮助。有出路吗?
答案 0 :(得分:3)
我无法直接在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
,正确注释,包括将其指向RevisionListenerImpl
类,作为Envers应该使用的侦听器实现。
现在,在每个子项目中,您需要做的就是:
第一个是关于JPA项目如何从每个子项目获取详细信息的门户。在Spring Web应用程序中,这可能只是一些Spring服务bean。例如。
第二个是每个线程在调用任何JPA之前需要做的事情。同样在Spring Web应用程序中,这可能是某种类型的Web过滤器,它在调用用户代码之前在过滤器链的顶部执行,以确保正确设置ThreadLocal。
检索登录用户的实现因父母maven项目而异。
回到这一点,正如您在上面所看到的,RevisionInfoProvider
的抽象层很好地处理了这个问题。您为Envers构建了一个通用框架来完成它的工作,同时保持足够的灵活性,以便每个父项目都可以根据需要进行分歧。
如果你确实发现自己处于这种情况,你需要分别在每个父项目中实现修订实体和监听器或遵循我上面提到的但是使用满足要求的修订实体两个父模块。
您需要确保在正在检查实体的引导阶段,JPA模块可以接收修订实体。
希望这有帮助。