【问题标题】:Comparing objects that implement the same interface with javers将实现相同接口的对象与 javers 进行比较
【发布时间】:2017-08-10 19:27:15
【问题描述】:

我正在使用 javers (https://javers.org/) 并尝试比较实现相同接口的两个对象。作为一个例子,我用苹果和橘子设置了一个测试。 Apples to Apples 工作正常,但不是 Apples to Oranges。它似乎运行了比较,但没有获取新值。

如果我有一个 Fruit 超类和扩展它的苹果和橘子,但接口没有运气,这很好用。 任何熟悉这个 API 的人都可以为我指明正确的方向。

这是模型代码:

@TypeName("FruitIface")
@Entity
public interface FruitIface {

public final static String SIZE_SMALL = "Small";
public final static String SIZE_LARGE = "Large";
public final static String CONDITION_RIPE = "Ripe";
public final static String CONDITION_NOT_RIPE = "Not Ripe";

public String getSize();
public String getCondition();
public Double getWeight();
public Date getSellBy();

}



@TypeName("FruitIface")
@Entity
public class Apple implements FruitIface {


private String size;
private String condition;
private Double weight;
private Date sellBy;
@Id
private String compareId;

public Apple (String id,String size, String condition, Double weight, Date sellBy){
    this.compareId = id;
    this.size = size;
    this.condition = condition;
    this.weight = weight;
    this.sellBy = sellBy;
}
    ....

}


@TypeName("FruitIface")
@Entity
public class Orange implements FruitIface {

@PropertyName("size")
private String size;
private String condition;
private Double weight;
private Date sellBy;
@Id
private String compareId;


public Orange (String id, String size, String condition, Double weight, Date sellBy){
    this.compareId = id;
    this.size = size;
    this.condition = condition;
    this.weight = weight;
    this.sellBy = sellBy;
}
....
}

测试用例:

@Test public void testCompareAppleToAppleIface() {
    Apple appleOne = new Apple("01",FruitIface.SIZE_LARGE,FruitIface.CONDITION_RIPE, 0.3, new Date());
    Apple appleTwo = new Apple("01",FruitIface.SIZE_SMALL,FruitIface.CONDITION_RIPE, 0.2, new Date());

    LOGGER.info("\n\nComparing apples to apples...");
    Diff diff = javers.compare(appleOne, appleTwo);
    LOGGER.info("diff: " + diff);

}


@Test public void testCompareAppleAndOrangeIface() {
    Apple apple = new Apple("01",FruitIface.SIZE_LARGE,FruitIface.CONDITION_RIPE, 0.3, new Date()); //(String size, String condition, Double weight, Date sellBy)
    Orange orange = new Orange("01",FruitIface.SIZE_SMALL,FruitIface.CONDITION_RIPE, 0.2, new Date());


    LOGGER.info("\n\nComparing apples and oranges IFace...");
    Diff diff = javers.compare(apple, orange);
    LOGGER.info("diff: " + diff);
}

结果:

Comparing apples to apples...
[main] INFO xxx.compare.test.JaversCompareTestIface - diff: Diff:
1. ValueChange{globalId:'FruitIface/01', property:'size', oldVal:'Large', newVal:'Small'}
2. ValueChange{globalId:'FruitIface/01', property:'weight', oldVal:'0.3', newVal:'0.2'}


Comparing apples and oranges IFace...
[main] INFO xxx.compare.test.JaversCompareTestIface - diff: Diff:
1. ValueChange{globalId:'FruitIface/01', property:'size', oldVal:'Large', newVal:''}
2. ValueChange{globalId:'FruitIface/01', property:'condition', oldVal:'Ripe', newVal:''}
3. ValueChange{globalId:'FruitIface/01', property:'weight', oldVal:'0.3', newVal:''}
4. ValueChange{globalId:'FruitIface/01', property:'sellBy', oldVal:'Thu Aug 10 12:14:45 PDT 2017', newVal:''}
5. ValueChange{globalId:'FruitIface/01', property:'compareId', oldVal:'01', newVal:''}

【问题讨论】:

    标签: java object compare javers


    【解决方案1】:

    对多个类使用相同的 @TypeName 是一种滥用,原因与对多个 Java 类使用相同的类名相同。

    在这种情况下,JaVers 应该抛出一个异常,而不是因为 JaVers 类型系统被混淆了,所以你会得到某种随机结果。

    在当前版本的 JaVers 中,即使 Apple 和 Orange 都实现了 Fruit 接口,也无法将它们进行比较。 JaVers 匹配具有相同GlobalId 的对象并进行比较。 当您拥有 ID 为 1 的 Apple 和 ID 为 1 的 Orange 时,它​​们的 GlobalId 为 Apple#1Orange#1,因此它们不会作为同一对象的两个版本匹配。

    【讨论】:

    • 我明白你的反应......有点。我想做的是将苹果和橙子比作水果。所以我有一个水果接口和接口的两个实现(苹果和橙子)。我尝试从苹果和橙色中删除所有注释,然后运行测试。我从 javers 那里得到的是新对象和删除的对象。根据文档,听起来可以比较具有相同 iface 的对象:映射 ProTips 首先,尝试映射高级抽象类或接口。例如,如果你所有的实体都扩展了某个抽象类,你应该只映射这个类。
    • 嗯。如果我扩展类,则该策略有效... @TypeName("FruitSuper") @Entity public class FruitSuper {...} @TypeName("FruitSuper") public class AppleSub extends FruitSuper {...} @TypeName ("FruitSuper") public class OrangeSub extends FruitSuper {...} 比较苹果和橙子子类相同的 id... [main] INFO xxx.compare.test.JaversCompareTestSuper - diff: Diff: 1. ValueChange{globalId:'FruitSuper/ 01', property:'size', oldVal:'Large', newVal:'Small'} 2. ValueChange{globalId:'FruitSuper/01', property:'weight', oldVal:'0.3', newVal:'0.2' } 是功能还是错误?
    • 这就是Java中继承和接口的工作方式。如果 Apple 扩展 Fruit 和 Orange 扩展 Fruit,两者都是 Fruits,因此可以进行比较。如果 Apple 实现了 Serializable 而 Orange 实现了 Serializable 并不意味着 Apple 可以与 Orange 相提并论。
    • 是的,这又回到了我原来的问题。 Javers 允许我将 Fruit 的两个子类(苹果和橙子)与 Fruit 进行比较。它不允许我比较实现 Fruit 接口的两个对象(apple 和 orange),即使 globalId 匹配。这是设计使然吗?我从文档中得到的印象是,您可以比较两个共享接口的对象,即 FruitIface
    • 是的,这是设计使然,不会更改。顺便提一句。您能否指出文档中可能具有误导性的部分?
    猜你喜欢
    • 2015-10-25
    • 2019-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-21
    • 2022-09-30
    • 2017-12-23
    相关资源
    最近更新 更多