Javers - 使用定义的规则比较字符串、集合和布尔值
Javers - comparison String, Collection and Boolean with defined rules
我有2个类:
@Data
@Builder
public class Boss {
private String name;
private List<Employee> subordinates;
}
@Data
@Builder
public class Employee {
private String name;
private Boolean hasDrivingLicense;
private List<Employee> colleagues;
}
还有我自己定义的比较器(规则):
public class StringComparator implements CustomValueComparator<String> {
public boolean equals(String s, String t1) {
return (s != null && s.equals("") && t1 == null) || (s == null && t1 != null && t1.equals(""));
}
public String toString(String s) {
return s;
}
}
public class CollectionComparator<T> implements CustomValueComparator<Collection<T>> {
public boolean equals(Collection<T> ts, Collection<T> t1) {
return (ts == null && t1 != null && t1.isEmpty()) || (ts != null && ts.isEmpty() && t1 == null);
}
public String toString(Collection<T> ts) {
return ts.toString();
}
}
public class BooleanComparator implements CustomValueComparator<Boolean> {
public boolean equals(Boolean aBoolean, Boolean t1) {
return (aBoolean == null && t1 != null && t1.equals(false))
|| (aBoolean != null && aBoolean.equals(false) && t1 == null);
}
public String toString(Boolean aBoolean) {
return aBoolean.toString();
}
}
定义了这些比较器,以便将空字符串视为与 null 相同,将空集合视为与 null 相同,将布尔 false 视为与 null 相同。
在主要方法中,我尝试比较 2 个对象,以检查定义的比较器是否有效。
public static void main(String[] args) {
Employee employee1 = Employee.builder()
.name("Krzysztof")
.colleagues(new ArrayList<>())
.hasDrivingLicense(false)
.build();
Employee employee2 = Employee.builder()
.name("Krzysztof")
.colleagues(null)
.hasDrivingLicense(null)
.build();
Boss boss1 = Boss.builder()
.name("")
.subordinates(Arrays.asList(employee1))
.build();
Boss boss2 = Boss.builder()
.name(null)
.subordinates(Arrays.asList(employee2))
.build();
final Javers javers = JaversBuilder.javers()
.registerValue(CollectionComparator.class)
.registerValue(StringComparator.class)
.registerValue(BooleanComparator.class)
.build();
final Diff diff = javers.compare(boss1, boss2);
System.out.println(diff.getChanges().size() == 0);
System.out.println(diff.getChanges().size());
System.out.println(diff);
}
不幸的是,比较没有按预期进行。在 JaversBuilder 中,我尝试添加 .registerValue(String.class, (a, b) -> StringUtils.equals(a,b)) 但它也不起作用。
打印结果:
false
2
Diff:
* changes on Boss/ :
- 'name' value changed from '' to ''
- 'subordinates/0.hasDrivingLicense' value changed from 'false' to ''
我应该更改什么才能使其正常工作。如果比较器正常工作在此示例中,diff 不会有任何更改
我解决了我的问题。覆盖接口 CustomPropertyComparator 就足够了。
public class StringComparator2 implements CustomPropertyComparator<String, SetChange> {
@Override
public Optional<SetChange> compare(String s, String t1, PropertyChangeMetadata propertyChangeMetadata, Property property) {
// compare
}
public boolean equals(String s, String t1) {
// equals like above
}
public String toString(String s) {
// toString like above
}
}
在主要方法中:
final Javers javers = JaversBuilder.javers()
.registerCustomType(String.class, new StringComparator2())
.registerCustomType(Boolean.class, new BooleanComparator2())
.build();
final Diff diff = javers.compare(boss1, boss2);
System.out.println(diff.getChanges().size() == 0);
System.out.println(diff.getChanges().size());
System.out.println(diff);
而且我发现 JaVers 就是这样工作的,并将 null 视为空集合。所以不需要 CollectionComparator。
我认为这个问题是由于您假设 CustomValueComparators
可以为空值提供一些自定义逻辑造成的。这种假设是合理的,但却是错误的。当前,CustomValueComparators
始终获取非空值进行比较。 Javers 自己处理 nuls。
我创建了一个问题来管理这个 https://github.com/javers/javers/issues/1075
我有2个类:
@Data
@Builder
public class Boss {
private String name;
private List<Employee> subordinates;
}
@Data
@Builder
public class Employee {
private String name;
private Boolean hasDrivingLicense;
private List<Employee> colleagues;
}
还有我自己定义的比较器(规则):
public class StringComparator implements CustomValueComparator<String> {
public boolean equals(String s, String t1) {
return (s != null && s.equals("") && t1 == null) || (s == null && t1 != null && t1.equals(""));
}
public String toString(String s) {
return s;
}
}
public class CollectionComparator<T> implements CustomValueComparator<Collection<T>> {
public boolean equals(Collection<T> ts, Collection<T> t1) {
return (ts == null && t1 != null && t1.isEmpty()) || (ts != null && ts.isEmpty() && t1 == null);
}
public String toString(Collection<T> ts) {
return ts.toString();
}
}
public class BooleanComparator implements CustomValueComparator<Boolean> {
public boolean equals(Boolean aBoolean, Boolean t1) {
return (aBoolean == null && t1 != null && t1.equals(false))
|| (aBoolean != null && aBoolean.equals(false) && t1 == null);
}
public String toString(Boolean aBoolean) {
return aBoolean.toString();
}
}
定义了这些比较器,以便将空字符串视为与 null 相同,将空集合视为与 null 相同,将布尔 false 视为与 null 相同。 在主要方法中,我尝试比较 2 个对象,以检查定义的比较器是否有效。
public static void main(String[] args) {
Employee employee1 = Employee.builder()
.name("Krzysztof")
.colleagues(new ArrayList<>())
.hasDrivingLicense(false)
.build();
Employee employee2 = Employee.builder()
.name("Krzysztof")
.colleagues(null)
.hasDrivingLicense(null)
.build();
Boss boss1 = Boss.builder()
.name("")
.subordinates(Arrays.asList(employee1))
.build();
Boss boss2 = Boss.builder()
.name(null)
.subordinates(Arrays.asList(employee2))
.build();
final Javers javers = JaversBuilder.javers()
.registerValue(CollectionComparator.class)
.registerValue(StringComparator.class)
.registerValue(BooleanComparator.class)
.build();
final Diff diff = javers.compare(boss1, boss2);
System.out.println(diff.getChanges().size() == 0);
System.out.println(diff.getChanges().size());
System.out.println(diff);
}
不幸的是,比较没有按预期进行。在 JaversBuilder 中,我尝试添加 .registerValue(String.class, (a, b) -> StringUtils.equals(a,b)) 但它也不起作用。 打印结果:
false
2
Diff:
* changes on Boss/ :
- 'name' value changed from '' to ''
- 'subordinates/0.hasDrivingLicense' value changed from 'false' to ''
我应该更改什么才能使其正常工作。如果比较器正常工作在此示例中,diff 不会有任何更改
我解决了我的问题。覆盖接口 CustomPropertyComparator 就足够了。
public class StringComparator2 implements CustomPropertyComparator<String, SetChange> {
@Override
public Optional<SetChange> compare(String s, String t1, PropertyChangeMetadata propertyChangeMetadata, Property property) {
// compare
}
public boolean equals(String s, String t1) {
// equals like above
}
public String toString(String s) {
// toString like above
}
}
在主要方法中:
final Javers javers = JaversBuilder.javers()
.registerCustomType(String.class, new StringComparator2())
.registerCustomType(Boolean.class, new BooleanComparator2())
.build();
final Diff diff = javers.compare(boss1, boss2);
System.out.println(diff.getChanges().size() == 0);
System.out.println(diff.getChanges().size());
System.out.println(diff);
而且我发现 JaVers 就是这样工作的,并将 null 视为空集合。所以不需要 CollectionComparator。
我认为这个问题是由于您假设 CustomValueComparators
可以为空值提供一些自定义逻辑造成的。这种假设是合理的,但却是错误的。当前,CustomValueComparators
始终获取非空值进行比较。 Javers 自己处理 nuls。
我创建了一个问题来管理这个 https://github.com/javers/javers/issues/1075