gpt4 book ai didi

Hibernate Envers 修订之间的增量

转载 作者:行者123 更新时间:2023-12-05 03:02:54 26 4
gpt4 key购买 nike

我需要为项目中的所有 CRUD 操作实现审计历史记录。该项目使用 Spring JPA Data Rest。我四处寻找好的图书馆来完成所需的任务,并遇到了这个 Hibernate Envers ,这看起来非常好并且易​​于实现。将其合并到我的项目中后,我能够记录所有 CRUD 操作的修订。

现在我需要公开更改,用户可以在其中看到作为任何修订的一部分所做的更改。这是我想要增量输出的方式(为了便于阅读,我将其置于 JSON 格式)。

[
{
"date": "9 may 2018, 6:06 pm",
"user": "user.name (FName LName)",
"actions": [
{
"field": "name",
"oldValue": "Old Name very long",
"newValue": "New Name also quite long."
},
{
"field": "score",
"oldValue": 2,
"newValue": 4
},
{
"field": "average_rating",
"oldValue": "AA",
"newValue": "A"
}
]
},{
"date": "10 may 2018, 5:06 pm",
"user": "user.name (FName LName)",
"actions": [
{
"field":"name",
"oldValue": "Old Name",
"newValue": "New Name"
},
{
"field":"score",
"oldValue": 1,
"newValue": 6
},
{
"field":"average_rating",
"oldValue": "D",
"newValue": "A+"
},
{
"field":"rating",
"oldValue": "A-",
"newValue": "A"
}
]
},{
"date": "10 may 2018, 5:06 pm",
"user": "user.name3 (FName3 LName3)",
"actions": [
{
"field":"average_rating",
"oldValue": "D",
"newValue": "B"
},
{
"field":"rating",
"oldValue": "C",
"newValue": "D"
}
]
},{
"date": "11 may 2018, 5:06 pm",
"user": "user2.name2 (FName2 LName2)",
"actions": [
{
"field":"score",
"oldValue": 3,
"newValue": 4
},
{
"field":"average_rating",
"oldValue": "C",
"newValue": "B"
}
]
},{
"date": "9 apr 2018, 3:00 pm",
"user": "user.name (FName LName)",
"actions": [
{
"field":"name",
"oldValue": "Old Name very long",
"newValue": "New Name also quite long."
},
{
"field":"score",
"oldValue": 5,
"newValue": 3
},
{
"field":"average_rating",
"oldValue": "AA",
"newValue": "B"
},
{
"field":"edf_score",
"oldValue": 4,
"newValue": 2
},
{
"field":"edf_average_rating",
"oldValue": "BBB+",
"newValue": "BB"
}
]
}
]

我需要以 JSON-HAL 格式公开这些内容。

提前致谢。

最佳答案

有几种方法可以完成您的要求,但这主要取决于您使用的 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();

这个查询实际上返回一个 List<Object[]>因为 forRevisionsOfEntity 的第二个参数是假的。如果此参数的值为真,则返回值为 List<YourEntityClass> .

来自 List 中的每个条目是一个基于以下配置的对象数组:

  • 索引 0 - YourEntityClass该修订版的实例
  • 索引 1 - 修订实体的具体实现(稍后会详细介绍)。
  • 索引 2 - RevisionType枚举值,ADD , MOD , 或 DEL .如果 forRevisionsOfEntity 的第三个参数是假的,永远不会有任何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;
}
}

这里的主要内容是在您的 resolveActions 中方法,你基本上使用反射或一些 java 对象差异库来确定两个实例之间的变化。如果您使用 withModifiedFlag 的想法,您可以为每个属性运行查询,但如果所讨论的实体类型有很多列,或者如果您倾向于进行大量修订,这可能会对您的系统造成负担。

如果您使用的是 Hibernate 5.3,我们添加了一个简化此过程的便捷方法,但它依赖于 withModifiedFlag概念也。在这种特殊情况下,您最初会运行原始查询的稍微不同的修改版本

List results = AuditReaderFactory.get( session ).createQuery()
.forRevisionsOfEntityWithChanges( YourEntityClass.class, false, true )
.add( AuditEntity.id().eq( entityId ) )
.addOrder( AuditEntity.revisionNumber().asc() )
.getResultList();

此查询返回与上述 5.2 相同类型的数组,只是它在对象数组中包含一个额外的对象:

  • 索引 3 - 作为已更改属性的字符串集合。

关于这种新方法的好主意不是使用反射或某种类型的差异库,就像我在 resolveActions 中提到的那样。 ,现在您已经明确知道哪些属性被更改了,这只是从对象实例中获取这些特定值的问题,这是非常简单的。

最后的方法仍然是 @Incubating所以它被认为是实验性的。我可能会看到更改索引 3,以便您返回 Tuple<String,Object>其中包含可能带有值的属性/字段名称,使用户使用起来更加直接。

关于Hibernate Envers 修订之间的增量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54331360/

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