Javers 不报告对象层次结构中的引用更改
Javers is not reporting references changes in object hierarchy
问题陈述
我正在试验 Javers 3.5.1 报告提交的更改的能力。似乎只有原始变化才会被报告;当实体层次结构中的对象引用发生更改时,更改不会被报告回来。
样本
这是一个示例:
Javers javers = JaversBuilder.javers().build();
RegexRegisteredService svc2 = new RegexRegisteredService();
// Set a reference to something
svc2.setUsernameAttributeProvider(new DefaultRegisteredServiceUsernameProvider());
svc2.setId(345);
javers.commit("345", svc2);
// change the reference
svc2.setUsernameAttributeProvider(new AnonymousRegisteredServiceUsernameAttributeProvider());
javers.commit("345", svc2);
List<Change> changes = javers.findChanges(QueryBuilder.byInstanceId("345",
RegexRegisteredService.class).build());
System.out.println(changes.size());
以上代码片段的结果为 0。
诊断
进一步的诊断显示包含 classes 中的对象引用有自己的 ID; findChanges()
函数只查看包含该 ID 的 class/entity,而不会向下遍历层次结构以查找其他引用和属性。当 InMemoryRepository 开始将历史快照与传递的 globalId 进行比较时,它只会查看父 globalId,而不会向下查看包含的列表 classes:
Iterator it = this.getAll().iterator();
while(it.hasNext()) {
CdoSnapshot snapshot = (CdoSnapshot) it.next();
if (snapshot.getGlobalId().equals(globalId)) {
filtered.add(snapshot);
}
...
这里传过来的globalId
是org.apereo.cas.services.RegexRegisteredService/345
。但是,此 id 中的任何内容都没有改变;真正改变的是映射到 org.apereo.cas.services.RegexRegisteredService/345#usernameAttributeProvider
的,它将永远不会被检索,因为上面的检查不满足相等条件。
层次结构是这样的:
public interface RegisteredService {}
public abstract class AbstractService implements RegisteredService {
// with setters and getters
private UsernameAttributeProviderInterface usernameAttributeProvider;
}
public class RegexRegisteredService extends AbstractService {}
备选方案?
换成这样怎么样?
Iterator it = this.getAll().iterator();
while(it.hasNext()) {
CdoSnapshot snapshot = (CdoSnapshot) it.next();
if (snapshot.getGlobalId().value().startsWith(globalId.value())) {
filtered.add(snapshot);
}
...
Javers 中是否缺少此功能,还是我遗漏了什么?想知道我是否应该设计自己的存储库 class?
事实证明我需要做一些非常简单的事情:
final List<Change> changes = javers.findChanges(
QueryBuilder.byInstanceId("345, RegexRegisteredService.class)
.withChildValueObjects()
.build());
参考:
https://javers.org/documentation/jql-examples/#child-value-objects-filter
您可能已将引用对象映射为 ValueObjects(这是默认设置)。在 JaVers 中,ValueObjects 被视为 属性 容器,并且在比较它们时它们的类型并不重要。这反映在 GlobalId 中:
org.apereo.cas.services.RegexRegisteredService/345#usernameAttributeProvider
如果要跟踪类型更改,需要将引用对象映射为实体
问题陈述
我正在试验 Javers 3.5.1 报告提交的更改的能力。似乎只有原始变化才会被报告;当实体层次结构中的对象引用发生更改时,更改不会被报告回来。
样本
这是一个示例:
Javers javers = JaversBuilder.javers().build();
RegexRegisteredService svc2 = new RegexRegisteredService();
// Set a reference to something
svc2.setUsernameAttributeProvider(new DefaultRegisteredServiceUsernameProvider());
svc2.setId(345);
javers.commit("345", svc2);
// change the reference
svc2.setUsernameAttributeProvider(new AnonymousRegisteredServiceUsernameAttributeProvider());
javers.commit("345", svc2);
List<Change> changes = javers.findChanges(QueryBuilder.byInstanceId("345",
RegexRegisteredService.class).build());
System.out.println(changes.size());
以上代码片段的结果为 0。
诊断
进一步的诊断显示包含 classes 中的对象引用有自己的 ID; findChanges()
函数只查看包含该 ID 的 class/entity,而不会向下遍历层次结构以查找其他引用和属性。当 InMemoryRepository 开始将历史快照与传递的 globalId 进行比较时,它只会查看父 globalId,而不会向下查看包含的列表 classes:
Iterator it = this.getAll().iterator();
while(it.hasNext()) {
CdoSnapshot snapshot = (CdoSnapshot) it.next();
if (snapshot.getGlobalId().equals(globalId)) {
filtered.add(snapshot);
}
...
这里传过来的globalId
是org.apereo.cas.services.RegexRegisteredService/345
。但是,此 id 中的任何内容都没有改变;真正改变的是映射到 org.apereo.cas.services.RegexRegisteredService/345#usernameAttributeProvider
的,它将永远不会被检索,因为上面的检查不满足相等条件。
层次结构是这样的:
public interface RegisteredService {}
public abstract class AbstractService implements RegisteredService {
// with setters and getters
private UsernameAttributeProviderInterface usernameAttributeProvider;
}
public class RegexRegisteredService extends AbstractService {}
备选方案?
换成这样怎么样?
Iterator it = this.getAll().iterator();
while(it.hasNext()) {
CdoSnapshot snapshot = (CdoSnapshot) it.next();
if (snapshot.getGlobalId().value().startsWith(globalId.value())) {
filtered.add(snapshot);
}
...
Javers 中是否缺少此功能,还是我遗漏了什么?想知道我是否应该设计自己的存储库 class?
事实证明我需要做一些非常简单的事情:
final List<Change> changes = javers.findChanges(
QueryBuilder.byInstanceId("345, RegexRegisteredService.class)
.withChildValueObjects()
.build());
参考: https://javers.org/documentation/jql-examples/#child-value-objects-filter
您可能已将引用对象映射为 ValueObjects(这是默认设置)。在 JaVers 中,ValueObjects 被视为 属性 容器,并且在比较它们时它们的类型并不重要。这反映在 GlobalId 中:
org.apereo.cas.services.RegexRegisteredService/345#usernameAttributeProvider
如果要跟踪类型更改,需要将引用对象映射为实体