2

https://github.com/javers/javers/issues/98で説明されているのと同様のユースケースがあります。

以下のコードでは、従属オブジェクトを更新して従業員ボブをコミットするときに、従属オブジェクトへの変更を JQL クエリから取得する必要があります。QueryBuilder.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'

ありがとう!

4

2 に答える 2

1

この場合、JaVers JQL はエンティティ結合をサポートしていないため、明確な解決策はありません。したがって、エンティティ Y のスナップショットから参照されるエンティティ X のスナップショットを見つける簡単な方法はありません。私が提案できるのは、DDD 集約 (エンティティとその子 ValueObjects) の形式で形成された DTO オブジェクトを準備し、これらの DTO を JaVers にコミットすることです。元のドメイン オブジェクトの代わりに。私はそれがエレガントなソリューションではないことを知っています。

于 2016-10-04T06:49:31.747 に答える
1

withChildValueObjects()フィルターは子 (依存) ValueObjects に対してのみ機能し、両方のクラスがエンティティとしてマップされています (@Id ann が存在します)。

Employeeとオブジェクトの間に明示的な親子関係がないためDependent、JaVers はそれらを同等に扱います。DependentValueObject としてマップすると、テストに合格します(@Id を削除するだけで十分です)。

于 2016-10-03T22:09:27.163 に答える