当前位置: 首页 > 知识库问答 >
问题:

JaVers不检测集合中对象属性的更改

金子平
2023-03-14

我想使用JaVers来跟踪我的Java对象的更改。基本示例工作正常,但我无法让它检测存储在集合中的对象的更改。

如果我扩展ChangeLogExample。更改例如其中一个子坐标的课堂示例:

public static void main(String[] args) {

    Javers javers = JaversBuilder.javers().build();
    Employee bob = new Employee("Bob", 9_000, "Scrum master" );
    javers.commit("hr.manager", bob);

    // do some changes and commit
    bob.setPosition("Team Lead");
    bob.setSalary(11_000);
    javers.commit("hr.director", bob);

    bob.addSubordinates(new Employee("Trainee One"), new Employee("Trainee Two"));
    javers.commit("hr.manager", bob);

    bob.getSubordinates().get(0).setAge(42); // <<<< This is the change I want to detect
    javers.commit("hr.manager", bob); 

    // when:
    List<Change> changes = javers.findChanges(
        QueryBuilder.byInstanceId("Bob", Employee.class).withChildValueObjects().build());
    String changeLog = javers.processChangeList(changes, new SimpleTextChangeLog());

    // then:
    System.out.println(changeLog);
}

这是打印的更改日志:

commit 3.0, author: hr.manager, 2017-06-06 11:17:17
  changed object: Employee/Bob
    list changed on 'subordinates' property: [(0).added:'Employee/Trainee One', (1).added:'Employee/Trainee Two']
commit 2.0, author: hr.director, 2017-06-06 11:17:17
  changed object: Employee/Bob
    value changed on 'position' property: 'Scrum master' -> 'Team Lead'
    value changed on 'salary' property: '9000' -> '11000'

因此,第一个下属的年龄变化不会显示在变更日志中。

使用withChildValueObjects()没有什么不同。

当我单独将更改提交给员工实例时,我会得到学员年龄的更改,但这不是我想要的(也不是我想要的)。

所以我的问题是:如何在变更日志中显示年龄的变更?

我使用的是JaVers 3.2.0

JaVers示例中的Employee类保持不变:https://github.com/javers/javers/tree/master/javers-core/src/test/java/org/javers/core/examples/model

main()方法只是从https://github.com/javers/javers/blob/master/javers-core/src/test/java/org/javers/core/examples/ChangeLogExample.java

共有1个答案

施飞鸿
2023-03-14

好的,这里有几个问题。首先,对象映射为实体。因此,在JaVers中,他们之间没有父母/子女关系(实际上是任何一种关系)。这就是为什么withChildValueObjects()过滤器在这里不适用的原因。它仅适用于实体拥有的ValueObjects,请参见http://javers.org/documentation/jql-examples/#child-值对象过滤器

不过,有两种方法可以改进您的查询。

>

将新的阴影应用编程接口与查询范围一起使用,请参见http://javers.org/documentation/jql-examples/#query-for-shadows这是一个新特性,将在该特性中得到改进。如果查询将选择两个实体的快照,您已经可以使用它了。

请参阅下面的代码:

def "should ... "(){
  given:
  Javers javers = JaversBuilder.javers().build()
  Employee bob = new Employee("Bob", 9_000, "Scrum master" )
  javers.commit("hr.manager", bob)

  // do some changes and commit
  bob.setPosition("Team Lead")
  bob.setSalary(11_000)
  javers.commit("hr.director", bob)

  bob.addSubordinates(new Employee("Trainee One"), new Employee("Trainee Two"))
  javers.commit("hr.manager", bob)

  bob.getSubordinates().get(0).setAge(42) // <<<< This is the change I want to detect
  bob.salary++ // !
  javers.commit("hr.manager", bob)

  when: "ask for the the right Entity instance"
  List changes = javers.findChanges(
          QueryBuilder.byInstanceId("Trainee One", Employee.class).build())

  then:
  println( javers.processChangeList(changes, new SimpleTextChangeLog()) )
  true

  when: "use the new Shadows"
  List shadows = javers.findShadows(
          QueryBuilder.byInstanceId("Bob", Employee.class)
                      .withShadowScopeDeep().build())

  then:
  shadows.each {
      assert it.get() instanceof Employee
  }
  Employee lastBobShadow = shadows[0].get()
  assert shadows[0].commitMetadata.id.majorId == 4
  assert lastBobShadow.subordinates[0].name == "Trainee One"
  assert lastBobShadow.subordinates[0].age == 42
}
 类似资料:
  • 断言集合中所有元素(第一个参数)的指定属性(第二个参数)是否为真值(truthy)。 使用 Array.every() 来检查每个传递的对象是否具有指定的属性,以及是否返回一个真值。 const truthCheckCollection = (collection, pre) => collection.every(obj => obj[pre]); truthCheckCollection([

  • 我正在评估javers,以便将其用于审计实体。我有一个嵌套的ValueObject集合的实体。我希望值对象上的每个属性更改都会生成实体的快照。只有在将值对象添加到集合中时才会创建快照。在我的例子中,我向集合添加了两个值对象,创建了实体的两个快照。第三次,我只是改变了value对象的一个属性,javers没有意识到这是对实体的改变,而是为内部value对象创建了一个快照。 我的问题是我的假设是否有效

  • 问题内容: 检查JavaScript中的对象属性是否为最佳方法是什么? 问题答案: 检查属性值是否为特殊值的通常方法是: 要检查对象是否实际上没有这样的属性,并因此在尝试访问它时默认情况下将返回: 检查与标识符关联的值是否为特殊值, 或者 尚未声明该标识符。注意:此方法是引用 未声明的标识符(注意:与的值不同)的唯一方法,且不会出现早期错误: 在ECMAScript 5之前的JavaScript版

  • 在Laravel中,如果执行查询: ...然后,是模型对象的集合。(基本上是一系列模型。) 但是,此数组的键仅为: ...所以如果我想改变,比如说,为24的对象,我不能这样做: ...因为这只会改变数组中的第25个元素,而不是id为24的元素。 如何通过任何属性/列(例如但不限于id/Color/age/etc)从集合中获取单个(或多个)元素? 当然,我可以这样做: ...但是,那太恶心了。 当然

  • 所以我做了两组物体,就像这样。 这些都是4位数的对象,所以它就像。。。 如果我有2个集合,set1和set2,我想更新set1和set2,只包含set1具有与set2的第一个属性匹配的最后一个属性的对象。 例如第1组中的1234将与第2组中的3456匹配。 我可以很容易地将其作为列表而不是集合来完成,但如果我能够理解过程,集合会感觉效率更高,但不确定如何返回对象属性的交集。任何帮助。 编辑:因为我

  • 我有一个带有子组件的组件。 在时间轴组件中,我有这些属性: 如何检查何时从时间轴组件对属性进行更改?每当编辑值发生更改时,我都需要发出该值。 我应该为编辑属性使用一个setter,然后从那里发出吗? 或者有其他方法吗?