如何检索关系的审核修改?(How to retrieve the audited revision

2019-06-24 07:43发布

这里是我的使用情况

我有两个实体:Personn和电子邮件(一@OneToMany关系)。 他们都进行审核。

首先,我创建一个新的Personn,用电子邮件(=>他们都有一个修订版1),然后我修改了电子邮件(=>的电子邮件有第2次修订,但Personn只有一个版本1)

在Web应用程序的最终用户只有一个视图来显示Personn的attributs也是自己的电子邮件attributs。 在这种观点我想说明这个Personn所有现有的版本。 但是,当我查询审核系统,它不会因为Personn没有被修改告诉我修改2。

我理解的技术问题,但在视最终用户的角度,他希望看到第2次修订,因为他修改了personn的电子邮件! 他不知道(而且不必知道),我们deciced划分这些信息转换成2个Java对象。 当然,这个问题不仅是Personn电子邮件的关系(我有很多这是在同一个视图中显示Personn和其他对象之间的关系 - ADRESS,工作,网站,卡,等等)

我想到了2种解决方案:

1查询所有关系知道,如果一个版本存在(但我想它会产生一个很大的请求或多个请求 - 我已经得到了很多关系)。

2 - 设置“hibernate.listeners.envers.autoRegister”为假,写我自己EnversIntegrator和事件的实现。 在事件实现(其覆盖默认Envers实现),当电子邮件的attributs已被修改,我将创建一个Personn ModWorkUnit(它不会被硬编码课程:perharps像@AuditedPropagation自定义注释上personn场)。 这种解决方案的缺陷是创造了很多一排Personn即使它没有被修改。

你怎么看待这些解决方案是什么? 你知道一个更好的办法来解决那种用例吗?

感谢您的建议。

Answer 1:

我试图执行第二个解决方案:

  1. 首先我的积分增加了一个新的职位更新监听器(RevisionOnCollectionPostUpdateEventListenerImpl)

     public class RevisionOnCollectionUpdateIntegrator implements Integrator { private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, RevisionOnCollectionUpdateIntegrator.class.getName()); public static final String REGISTER_ON_UPDATE = "org.hibernate.envers.revision_on_collection_update"; @Override public void integrate(Configuration configuration, SessionFactoryImplementor sessionFactory, SessionFactoryServiceRegistry serviceRegistry) { final boolean autoRegister = ConfigurationHelper.getBoolean(REGISTER_ON_UPDATE, configuration.getProperties(), true); if (!autoRegister) { LOG.debug("Skipping 'revision_on_collection_update' listener auto registration"); return; } EventListenerRegistry listenerRegistry = serviceRegistry.getService(EventListenerRegistry.class); listenerRegistry.addDuplicationStrategy(EnversListenerDuplicationStrategy.INSTANCE); final AuditConfiguration enversConfiguration = AuditConfiguration.getFor(configuration, serviceRegistry.getService(ClassLoaderService.class)); if (enversConfiguration.getEntCfg().hasAuditedEntities()) { listenerRegistry.appendListeners(EventType.POST_UPDATE, new RevisionOnCollectionPostUpdateEventListenerImpl(enversConfiguration)); } } 
  2. 再之后的更新监听器(延伸):

     public class RevisionOnCollectionPostUpdateEventListenerImpl extends EnversPostUpdateEventListenerImpl { protected final void generateBidirectionalWorkUnits(AuditProcess auditProcess, EntityPersister entityPersister, String entityName, Object[] newState, Object[] oldState, SessionImplementor session) { // Checking if this is enabled in configuration ... if (!getAuditConfiguration().getGlobalCfg().isGenerateRevisionsForCollections()) { return; } // Checks every property of the entity, if it is an "owned" to-one relation to another entity. // If the value of that property changed, and the relation is bi-directional, a new revision // for the related entity is generated. String[] propertyNames = entityPersister.getPropertyNames(); for (int i = 0; i < propertyNames.length; i++) { String propertyName = propertyNames[i]; RelationDescription relDesc = getAuditConfiguration().getEntCfg().getRelationDescription(entityName, propertyName); if (relDesc != null && relDesc.isBidirectional() && relDesc.getRelationType() == RelationType.TO_ONE && relDesc.isInsertable()) { // Checking for changes Object oldValue = oldState == null ? null : oldState[i]; Object newValue = newState == null ? null : newState[i]; // Here is the magic part !!!!!!!!! // The super class verify if old and new value (of the owner value) are equals or not // If different (add or delete) then an audit entry is also added for the owned entity // When commented, an audit row for the owned entity is added when a related entity is updated // if (!Tools.entitiesEqual(session, relDesc.getToEntityName(), oldValue, newValue)) { // We have to generate changes both in the old collection (size decreses) and new collection // (size increases). if (newValue != null) { addCollectionChangeWorkUnit(auditProcess, session, entityName, relDesc, newValue); } if (oldValue != null) { addCollectionChangeWorkUnit(auditProcess, session, entityName, relDesc, oldValue); } // } } } } 

它似乎工作,但我一定要考多一点点。



Answer 2:

我一直无法使自定义后更新监听器解决方案的工作。 addCollectionChangeWorkUnit似乎并不存在,直到冬眠4.1在那里标记为私有。 EnversPostUpdateEventListenerImpl似乎在Hibernate 4.0在某些时候出现

我通过我的等效你一个实体的加入一个隐藏LASTUPDATED日期字段解决我的问题。

@Entity
public class A {
    private Date lastModified;
    @OneToMany(mappedBy = "a", cascade = CascadeType.ALL )
    private List<B> blist;
    public void touch(){
        lastModified=new Date();
    }
}

在相关实体(如你B场),我增加了以下内容:

public class B {
    @ManyToOne
    private A a; 

    @PreUpdate
    public void ensureParentUpdated(){
        if(a!=null){
            a.touch();
        }
    }
}

这确保了修订加入A每当增加了补正,即使它需要在许多实体的自定义代码到B点。



文章来源: How to retrieve the audited revision of relations?