Java 重写CompoundPropertyModel中对象的getter方法

Java 重写CompoundPropertyModel中对象的getter方法,java,wicket,Java,Wicket,下面是我在Wicket中使用CompoundPropertyModel时经常遇到的一个问题的简单示例: 这是我的实体Item及其模型ItemModel和控制器ItemController: public class Item implements Serializable { private static final long serialVersionUID = 1L; private long createdTimestamp; public Item(long

下面是我在Wicket中使用CompoundPropertyModel时经常遇到的一个问题的简单示例:

这是我的实体
Item
及其模型
ItemModel
和控制器
ItemController

public class Item implements Serializable {

    private static final long serialVersionUID = 1L;
    private long createdTimestamp;

    public Item(long createdTimestamp) {
        super();
        this.createdTimestamp = createdTimestamp;
    }

    public long getCreatedTimestamp() {
        return createdTimestamp;
    }

    public void setCreatedTimestamp(long createdTimestamp) {
        this.createdTimestamp = createdTimestamp;
    }
}

public class ItemModel extends CompoundPropertyModel<Item> {

    private static final long serialVersionUID = 1L;

    public ItemModel(Item object) {
        super(object);
    }
}

public class ItemController {

    public static int getDuration(Item item) {
        return Days.daysBetween(new DateTime(item.getCreatedTimestamp()), new DateTime()).getDays();
    }
}
这是可行的,但我不喜欢这个解决方案,因为如果您有很多实体,并且它们有很多字段,那么为所有实体创建和使用包装类可能会非常耗时

Item
已经有包装器,称为
ItemModel
。这就是为什么我想在这个类中创建getter方法并强制模型使用它们

以下是我的意思的一个例子:

public class ItemModel extends CompoundPropertyModel<Item> {

    private static final long serialVersionUID = 1L;

    public ItemModel(Item object) {
        super(object);
    }

    public Date getCreatedTimestamp() {
        return new Date(getObject().getCreatedTimestamp());
    }

    public int duration() {
        return ItemController.getDuration(getObject());
    }
}
公共类ItemModel扩展了CompoundPropertyModel{
私有静态最终长serialVersionUID=1L;
公共项模型(项对象){
超级(对象);
}
公共日期getCreatedTimestamp(){
返回新日期(getObject().getCreatedTimestamp());
}
公共整数持续时间(){
返回ItemController.getDuration(getObject());
}
}

但是在这种情况下,getter方法将被模型忽略。到目前为止,我还没有发现如何强制模型使用它们。有什么方法可以做到这一点吗?

您的模型没有被迫使用这些方法的原因是您的ItemModel类不是ItemView的子类。在Item模型的类声明中,使其扩展ItemView。此时父类的getter方法将被重写

更新


我刚刚意识到ItemModel已经扩展了一个不同的类。在Java中,一个类只能扩展一个父类。这是个棘手的问题。一种方法是使ItemView成为CompoundPropertyModel的内部类,然后ItemModel扩展CompoundPropertyModel。这应该行得通。如果您在google“使java类扩展多个类”中遇到问题,并且有很好的结果。

您的模型没有被迫使用这些方法的原因是您的ItemModel类不是ItemView的子类。在Item模型的类声明中,使其扩展ItemView。此时父类的getter方法将被重写

更新


我刚刚意识到ItemModel已经扩展了一个不同的类。在Java中,一个类只能扩展一个父类。这是个棘手的问题。一种方法是使ItemView成为CompoundPropertyModel的内部类,然后ItemModel扩展CompoundPropertyModel。这应该行得通。如果您在google“使java类扩展多个类”中遇到问题,并且效果很好。

CompoundPropertyModel在组件和属性之间有直接映射时非常有用。 但有时使用AROM更容易:

add(new Label("createdTimestamp", new AbstractReadOnlyModel<Date>() {
  public Date getObject() {
    return new Date(getModelObject().getCreatedTimestamp());
  }
});
(因为我们实际上只是从Long转换到Date,所以最好使用转换器。)

项已具有名为ItemModel的包装器。这就是为什么我会这么做 希望在此类中创建getter方法并强制模型使用 他们

除了在IModel中定义的方法之外,模型永远不应该有其他方法——在那里添加的任何方法都不会被Wicket调用,但最终会在组件之间产生不必要的依赖关系(比如面板需要一个ItemModel作为参数)

为所有实体创建和使用包装器类可能非常耗时

我想知道你为什么要定义ItemModel。最好只接受构造函数中的任何模型:

public ItemPanel(String id, IModel<Item> itemModel) {
    super(id, new CompoundPropertyModel<Item>(itemModel);
}
我见过其他我觉得有问题的模型实现。以下两种方法通常都有附加方法,可能是某种错误的气味:

new TransactionalModel(wrapped).commit()
new AsyncModel(wrapped).startAsync()
人们提倡创建与您的域相关的可重用模型,例如OrderSumModel,但我认为这是失败的。领域逻辑迟早会包含在模型中,您将看到以下模式出现:

BigDecimal sum = new OrderSumModel(order).getObject();
大多数时候,当我需要一些特别的东西时,我只是在编写匿名的内部类:

new Label("sum", new AbstractReadOnlyModel() {
  public BigDecimal getObject() {
    return service.calculateSum(getModelObject());
  }
});
如上所述,使用Java 8和Wicket 8,编写起来更加容易:

new Label("sum", () -> service.calculateSum(getModelObject()));
总是有例外:

当我需要一个具有复杂域逻辑的模型(例如OrderSumModel)时,我会将其作为一个嵌套的内部类。当我从多个位置需要它时,我会再次考虑。

当组件和属性之间有直接映射时,CompoundPropertyModel非常有用。 但有时使用AROM更容易:

add(new Label("createdTimestamp", new AbstractReadOnlyModel<Date>() {
  public Date getObject() {
    return new Date(getModelObject().getCreatedTimestamp());
  }
});
(因为我们实际上只是从Long转换到Date,所以最好使用转换器。)

项已具有名为ItemModel的包装器。这就是为什么我会这么做 希望在此类中创建getter方法并强制模型使用 他们

除了在IModel中定义的方法之外,模型永远不应该有其他方法——在那里添加的任何方法都不会被Wicket调用,但最终会在组件之间产生不必要的依赖关系(比如面板需要一个ItemModel作为参数)

为所有实体创建和使用包装器类可能非常耗时

我想知道你为什么要定义ItemModel。最好只接受构造函数中的任何模型:

public ItemPanel(String id, IModel<Item> itemModel) {
    super(id, new CompoundPropertyModel<Item>(itemModel);
}
我见过其他我觉得有问题的模型实现。以下两种方法通常都有附加方法,可能是某种错误的气味:

new TransactionalModel(wrapped).commit()
new AsyncModel(wrapped).startAsync()
人们提倡创建与您的域相关的可重用模型,例如OrderSumModel,但我认为这是失败的。领域逻辑迟早会包含在模型中,您将看到以下模式出现:

BigDecimal sum = new OrderSumModel(order).getObject();
大多数时候,当我需要一些特别的东西时,我只是在编写匿名的内部类:

new Label("sum", new AbstractReadOnlyModel() {
  public BigDecimal getObject() {
    return service.calculateSum(getModelObject());
  }
});
如上所述,使用Java 8和Wicket 8,编写起来更加容易:

new Label("sum", () -> service.calculateSum(getModelObject()));
总是有例外:
当我需要一个具有复杂域逻辑的模型(例如OrderSumModel)时,我会将其作为一个嵌套的内部类。只要我需要不止一个