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

Javers-在单个查询中跟踪子对象相对于父对象的更改

宰父阳焱
2023-03-14

我有https://github.com/javers/javers/issues/98中描述的类似用例。

在下面的代码中,当我更新dependent对象并提交Employee bob时,我希望对dependent的更改从JQL queryQueryBuilder中检索。byInstanceId(1L,Employee.class)

//update dependent's name ( WANT TO TRACK THIS FROM ROOT EMPLOYEE OBJECT)
Dependent aDep = bob.getDependentById(1L);
aDep.setName("Ramsey");
javers.commit("hr.manager", bob);

完整代码:

import lombok.Getter;
import lombok.Setter;
import org.javers.core.Javers;
import org.javers.core.JaversBuilder;
import org.javers.core.changelog.SimpleTextChangeLog;
import org.javers.core.diff.Change;
import org.javers.repository.jql.QueryBuilder;
import org.junit.Test;

import javax.persistence.Id;
import java.util.*;

public class JaversTests {

    @Test
    public void shouldPrintTextChangeLog() {
        // given:
        Javers javers = JaversBuilder.javers().build();

        //initial employee
        Employee bob = new Employee(1L, "Bob", 9_000, "Junior Developer");
        javers.commit("hr.manager", bob);

        // promoted
        bob.setPosition("Senior Developer");
        bob.setSalary(11_000);
        javers.commit("hr.director", bob);

        //add dependents
        bob.addDependents(new Dependent(1L, "Ram", "Son"), new Dependent(2L, "Kabita", "Daughter"));
        javers.commit("hr.manager", bob);

        //update dependent's name ( WANT TO TRACK THIS FROM ROOT EMPLOYEE OBJECT)
        Dependent aDep = bob.getDependentById(1L);
        aDep.setName("Ramsey");
        javers.commit("hr.manager", bob);

        List<Change> employeeChanges = javers.findChanges(
            QueryBuilder.byInstanceId(1L, Employee.class).withChildValueObjects().build());

        String employeeChangeLog = javers.processChangeList(employeeChanges, new SimpleTextChangeLog());

        System.out.println(employeeChangeLog);
    }
}

@Getter
@Setter
class Employee {
    @Id
    Long id;
    String name;
    double salary;
    String position;
    Set<Dependent> dependents = new HashSet<>();

    public Employee(Long id, String name, double salary, String position) {
        this.id = id;
        this.name = name;
        this.salary = salary;
        this.position = position;
    }

    void addDependents(Dependent... dependents) {
        getDependents().addAll(new LinkedList(Arrays.asList(dependents)));
    }

    Dependent getDependentById(Long id) {
        for (Dependent dep : getDependents()) {
            if (dep.getId() == id) {
                return dep;
            }
        }
        return null;
    }
}

@Setter
@Getter
class Dependent {

    @Id
    Long id;
    String name;
    String relation;

    public Dependent(Long id, String name, String relation) {
        this.id = id;
        this.name = name;
        this.relation = relation;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Dependent dependent = (Dependent) o;
        return Objects.equals(id, dependent.id);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }
}

我得到以下输出。这缺少从属名称更改(Ram到Ramsey)。

commit 3.0, author: hr.manager, Oct 3, 2016 12:45:57 PM
  changed object: us.sdata.enroll.Employee/1
    set changed on 'dependents' property: [added:'us.sdata.enroll.Dependent/2', added:'us.sdata.enroll.Dependent/1']
commit 2.0, author: hr.director, Oct 3, 2016 12:45:57 PM
  changed object: us.sdata.enroll.Employee/1
    value changed on 'salary' property: '9000.0' -> '11000.0'
    value changed on 'position' property: 'Junior Developer' -> 'Senior Developer'

谢谢

共有2个答案

赵镜
2023-03-14

在这种情况下没有干净的解决方案,因为JaVers JQL不支持实体连接。因此,没有简单的方法可以找到从实体Y的快照中引用的实体X的快照。我可以建议的是准备以DDD聚合形式形成的DTO对象(实体及其子ValueObjects),并将这些DTO提交给JaVers,而不是原始域对象。我知道这不是一个优雅的解决方案。

罗安宁
2023-03-14

withChildValueObjects()过滤器仅适用于子(从属)ValueObjects,您将两个类映射为实体(@Id ann存在)。

由于员工依赖对象之间没有明确的父子关系,JaVers平等对待它们。如果您将依赖映射为ValueObject,您的测试将通过(删除@Id就足够了)。

 类似资料:
  • SQL炼金术的特点是 Event Listening 整个核心和ORM使用的系统。在ORM中,有各种各样的事件侦听器钩子,这些钩子在API级别上记录在 ORM事件 . 这些年来,这些活动的集合不断增加,包括许多非常有用的新活动,以及一些与以前不太相关的旧活动。本节将尝试介绍主要事件挂钩以及它们可能被使用的时间。 执行事件 1.4 新版功能: 这个 Session 现在有一个完整的钩子,用来拦截代表

  • 当我对它进行降序排序时,它应该首先显示Parent3,因为它有一个Z。这是我当前的hql,它得到了1>2>3的错误结果: 如果没有distinct,尽管它选择了多个相同的父级,但它仍然很好。 我有一个模型设置如下: 编辑:在集合中按HQL顺序对其进行排序,尽管当双亲具有相同的children.name值时,它不会比较下一个可能的值。即。 如果Parent1有孩子abba,zeon Parent2有

  • 问题内容: 就像是 这是我想象的格式,但事实并非如此。什么会退回到对象的父级? 问题答案: JavaScript本身不提供此功能。而且我怀疑您是否可以创建这种类型的功能。例如: 鲍比属于谁?

  • 父类: 子电话对象(第一级): 我正在尝试获取person对象,其phone对象类型为home,其编号应包含“888”。 从上面的流代码,我能够得到手机对象。但是如何在相同的函数中获得该电话对象的父对象呢?。 我尝试了这种方式,我得到null不匹配的对象。

  • 问题内容: 假设我有2张桌子,分别称为父母和孩子。父母可以有零个到多个孩子,而一个孩子可以有1个到很多父母。如何找到作为两个特定孩子的父母的所有父母元素。 例如,假设我有父母[p_a,p_b,p_c,p_d]和孩子:[c_a,c_b]他们的结构如下: p_a的孩子为c_a p_b将c_b作为孩子 p_c将c_a和c_b都作为子代 p_d没有孩子 如何制定查询以选择p_c? 如果它们的结构中p具有[

  • 假设我有以下内容 这会产生如下所示的数组 我可以做一个级别,但是多个杠杆怎么样?我的伪代码类似于 但是对于无限的势能级,我该怎么做呢?