Hibernate 在修订之间休眠环境增量
我需要为我的项目上的所有CRUD操作实现审计历史记录。该项目使用SpringJPA数据Rest。我环顾四周寻找好的库来完成所需的任务,并发现了这个库,它看起来非常好而且易于实现。将其纳入我的项目后,我能够记录所有CRUD操作的修订 现在我需要公开更改,用户可以在其中看到作为任何修订的一部分所做的更改。下面是我希望增量输出的方式(为了便于阅读,我将其设置为JSON格式) 我需要以JSON-HAL格式公开这些内容Hibernate 在修订之间休眠环境增量,hibernate,spring-data-jpa,hibernate-envers,changeset,Hibernate,Spring Data Jpa,Hibernate Envers,Changeset,我需要为我的项目上的所有CRUD操作实现审计历史记录。该项目使用SpringJPA数据Rest。我环顾四周寻找好的库来完成所需的任务,并发现了这个库,它看起来非常好而且易于实现。将其纳入我的项目后,我能够记录所有CRUD操作的修订 现在我需要公开更改,用户可以在其中看到作为任何修订的一部分所做的更改。下面是我希望增量输出的方式(为了便于阅读,我将其设置为JSON格式) 我需要以JSON-HAL格式公开这些内容 提前感谢。有几种方法可以实现您的要求,但主要取决于您使用的Hibernate和Enve
提前感谢。有几种方法可以实现您的要求,但主要取决于您使用的Hibernate和Envers版本。如果您使用的是Hibernate 5.2及之前的版本,那么为了确定所需的信息,您的代码将需要进行一些额外的处理 我假设您拥有您感兴趣的实体的主键
List results = AuditReaderFactory.get( session ).createQuery()
.forRevisionsOfEntity( YourEntityClass.class, false, true )
.add( AuditEntity.id().eq( entityId ) )
.addOrder( AuditEntity.revisionNumber().asc() )
.getResultList();
此查询实际上返回一个列表
,因为forRevisionsOfEntity
的第二个参数为false。如果此参数的值为true,则返回值将为List
由此可知,列表中的每个条目都是基于以下配置的对象数组:
- 索引0—该修订版的
YourEntityClass
实例
- 索引1-修订实体的具体实现(稍后将对此进行详细介绍)
- 索引2-
RevisionType
枚举值,可以是ADD
,MOD
,也可以是DEL
。如果修改实体
的的第三个参数为false,则永远不会有任何DEL
类型
在这一点上,逻辑变得类似于:
YourEntityClass previousInstance = null;
for ( int i = 0; i < results.size(); ++i ) {
Object[] row = (Object[]) results.get( i );
if ( previousInstance == null ) {
// this is the first revision, consider nothing changed here
// so store a reference to it for the next row.
previousInstance = row[0];
}
else {
final YourRevisionEntity revEntity = (YourRevisionEntity) row[1];
final String userName = revEntity.getUserName();
final long revisionTimestamp = revEntity.getTimestamp();
final YourEntityClass currentInstance = (YourEntityClass) row[0];
List<Action> actions = resolveActions( previousInstance, currentInstance );
// build your things
previousInstance = currentInstance;
}
}
此查询返回的数组类型与上面提到的5.2类型相同,只是在对象数组中包含一个附加对象:
- 索引3-已更改属性的字符串集合
这种新方法的好主意是,不要像我在forresolveActions
中提到的那样使用反射或某种类型的差异库,现在您已经知道具体更改了哪些属性,只需从对象实例中获取那些特定的值,这非常简单
最后一种方法仍在酝酿中,因此被认为是实验性的。我可能会看到索引3发生了变化,从而返回一个元组
,其中可能包含属性/字段名和值,让用户可以更直接地使用它。您能具体告诉我您使用的是哪个版本的Hibernate&Envers吗,因为这对哪些API最适合您所需的输出有一定的影响?您好@Naros,Hibernate和EnversHi@Naros的最终版本都是5.2.17。谢谢您的回复。我所做的正是您刚才描述的(根据5.2.17版)。我使用java对象差异库来比较这两个对象。你能告诉我一件事吗?我能把envers升级到最新版本,比如说5.4.1.Final,但保持hibernate到5.2.17,并获取已更改/添加/删除的属性集合吗?属性列表可能会包括所有属性,无论它们是否在修订之间添加/更新/删除。遗憾的是,您不能。由于hibernate envers
和hibernate core
都是串联构建的,因此关键是要使用相同的版本部署它们,以避免两个工件之间的兼容性问题。好的,谢谢。如果需要检索实体的特定修订的修订历史记录。我的代码在正确的下面吗?AuditQuery AuditQuery=AuditReaderFactory.get(entityManager).createQuery().forEntitiesAtRevision(entityClass,revisionId).add(AuditEntity.id().eq(financialGroupId))@SuppressWarnings(“未选中”)列表resultList=auditQuery.getResultList();if(resultList.size()!=1){抛出新的IllegalStateException(“未找到修订处的实体”);}返回resultList.get(0);}你好,纳罗斯,谢谢你。如果需要检索实体的特定修订的修订历史记录。我的代码在正确的下面吗<代码>AuditQuery AuditQuery=AuditReaderFactory.get(entityManager).createQuery().ForentiesAtRevision(entityClass,revisionId).add(AuditEntity.id().eq(financialGroupId))@SuppressWarnings(“未选中”)列表resultList=auditQuery.getResultList();if(resultList.size()!=1){抛出新的IllegalStateException(“未找到修订处的实体”);}返回resultList.get(0);}代码>看起来不错,是的。请注意,如果该修订恰好是描述删除的修订,那么该方法将不返回任何结果,因为它被定义为仅返回插入和更新。
YourEntityClass previousInstance = null;
for ( int i = 0; i < results.size(); ++i ) {
Object[] row = (Object[]) results.get( i );
if ( previousInstance == null ) {
// this is the first revision, consider nothing changed here
// so store a reference to it for the next row.
previousInstance = row[0];
}
else {
final YourRevisionEntity revEntity = (YourRevisionEntity) row[1];
final String userName = revEntity.getUserName();
final long revisionTimestamp = revEntity.getTimestamp();
final YourEntityClass currentInstance = (YourEntityClass) row[0];
List<Action> actions = resolveActions( previousInstance, currentInstance );
// build your things
previousInstance = currentInstance;
}
}
List results = AuditReaderFactory.get( session ).createQuery()
.forRevisionsOfEntityWithChanges( YourEntityClass.class, false, true )
.add( AuditEntity.id().eq( entityId ) )
.addOrder( AuditEntity.revisionNumber().asc() )
.getResultList();