gpt4 book ai didi

java - Hibernate envers 在没有更改时创建记录

转载 作者:行者123 更新时间:2023-11-29 06:55:04 28 4
gpt4 key购买 nike

我一直在寻找一种方法,让 envers 不记录自上次记录以来没有修改的任何我合并的实体。事实证明,这应该是恩弗斯的正常行为(没有修改就没有审计)。

实体只有 @Audited 注释,但即使自上次审计以来没有变化,它们也会继续接受审计。这是我的 persitence.xml 的配置:

<property name="org.hibernate.envers.revision_field_name" value="revision" />
<property name="org.hibernate.envers.revision_type_field_name" value="revision_type" />
<property name="org.hibernate.envers.revision_on_collection_change" value="false"/>
<property name="org.hibernate.envers.store_data_at_delete" value="true"/>

我找到了这个 Hibernate Envers: Auditing an object, calling merge on it, gives an audit record EVERY time even with no change?但没有答案。

我的一些 equals()/hascode() 方法仅测试 ID(主键),但我没有找到关于这之间如何相关的任何主题。

我也看到有一个新参数可以查看哪个字段发生了变化,但我认为这也与我的问题无关。

如果重要的话,我正在使用 Postgresql。

对这种行为有什么想法吗?目前我唯一的解决方案是通过 entityManager 获取实体并比较它们(如果涉及到这一点,我将使用一些基于反射的 API)。

最佳答案

问题不是来自应用程序,而是来自代码本身。我们的实体有一个字段“lastUpdateDate”,它在每个 merge() 的当前日期设置。合并后由envers进行比较,因此该字段自上次修订以来发生了变化。

对于那些好奇的人,版本之间的变化在 org.hibernate.envers.internal.entities.mapper.MultiPropertyMapper.map() 中评估(至少在 evers 4.3.5.Final 上)如果 oldStatenewState 之间有任何变化,则返回 true。它根据所比较的属性使用特定的映射器。


编辑:我将在此处说明我是如何解决问题的,但也可以使用 Dagmar 的解决方案。然而,我的可能有点棘手和肮脏。

我使用 Envers 的 EnversPostUpdateEventListenerImpl 作为 The official documentation 中的描述和 various SO answers : 我创建了我的并强制 Envers 使用它。

@Override
public void onPostUpdate(PostUpdateEvent event) {
//Maybe you should try catch that !
if ( event.getOldState() != null ) {
final EntityPersister entityPersister = event.getPersister();
final String[] propertiesNames = entityPersister.getPropertyNames();

for ( int i = 0; i < propertiesNames.length; ++i ) {
String propertyName = propertiesNames[i];
if(checkProperty(propertyName){
event.getOldState()[i] = event.getState()[i];
}
}
// Normal Envers processing
super.onPostUpdate(event);
}

我的 checkProperty(String propertyName) 刚刚检查它是否是更新日期属性(propertyName.endsWith("lastUpdateDate") 因为它们在我们的应用程序中就是这样) .诀窍是,我将旧状态设置为新状态,所以如果这是我实体中唯一修改的字段,它不会审核它(用 envers 保存它)。但是,如果有其他字段被修改,Envers 将使用这些修改的字段和正确的 lastUpdateDate 审计实体。

我也遇到了一个问题,oldState 是没有设置 hh:mm:ss 的时间(只有零),而新状态是在同一天设置了小时数。所以我使用了类似的技巧:

Date oldDtEffet = (Date) event.getOldState()[i];
Date newDtEffet = (Date) event.getState()[i];
if(oldDtEffet != null && newDtEffet != null &&
DateUtils.isDateEqualsWithoutTime(oldDtEffet,newDtEffet)){
event.getOldState()[i] = event.getState()[i];
}

(注意:您必须重新实现所有事件监听器,即使它们只是继承 Envers 类,也没有解决办法。确保 org.hibernate.integrator.spi.Integrator 在您的应用程序中)

关于java - Hibernate envers 在没有更改时创建记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36134758/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com