JSF SelectOneMenu HashMap Converter有错误的instanceOf

时间:2013-01-17 13:18:07

标签: jsf selectonemenu

在我的Entity类中,我有一个HashMap。现在我正在尝试创建一个选择此地图,以便能够选择对象。所以我创建了以下类:

HorseConverter:

@Named
public class HorseConverter implements Converter{

    @EJB
    private HorseBean bean;

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        return bean.getHorse(Long.valueOf(value));
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        if(!(value instanceof Horse)){
            throw new ConverterException(new FacesMessage("Object is not a Horse"));
        } else {
            Horse h = (Horse) value;
            return Long.toString(h.getId());
        }
    }

}

种族实体:

public Map<Horse, Integer> getHorses() {
        return horses;
    }

    public void setHorses(HashMap<Horse, Integer> horses) {
        this.horses = horses;
    }

我的观点:

Horse:
<h:selectOneMenu value="#{betController.horse}" converter="#{horseConverter}">
    <f:selectItems value="#{raceController.selectedRace.horses}" var="h" itemLabel="#{h.nickName}" itemValue="#{h}"/>
</h:selectOneMenu>

似乎我得到的价值不是马的一个实例。我检查了以下链接: https://stackoverflow.com/tags/selectonemenu/info因此,密钥似乎被自动用作值。但即使编写h.key也没有什么区别。

编辑: 这是来自Horse Entity的哈希和等于代码:

@Override
    public int hashCode() {
        int hash = 7;
        hash = 97 * hash + (int) (this.id ^ (this.id >>> 32));
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final Horse other = (Horse) obj;
        if (this.id != other.id) {
            return false;
        }
        return true;
    }

2 个答案:

答案 0 :(得分:0)

你有没有在Horse()对象中覆盖hashcode()和equals()?

你的转换器需要equals()覆盖才能工作。如果不这样做,只有两个对同一个Horse()实例的引用将是相同的,而不是两个具有完全相同状态的单独实例。集合创建一个隐式副本进行比较,因此在这种情况下,您不会在堆上有单个实例。

不要忘记equals()对象中的参数是Object(),而不是Horse()。

如果不覆盖hashcode(),则每个Horse实例的哈希码都不同。这意味着你很难找到合适的马进行比较,即使你的马在逻辑上是等价的,因为你将会有多个实例,你将比较你的HashMap中的马。

有关详细信息,请参阅Effective Java by Joshua Bloch的本章。

答案 1 :(得分:0)

您无法在var值上使用Map。只有当您使用<f:selectItems>而不是List<Horse>时,此特定Map<Horse, Integer>构造才有效。

public List<Horse> getHorses() {
    return horses;
}

如果你真的想使用Map,那么你应该返回Map<String, Horse>,其中StringHorse的昵称。

public Map<String, Horse> getHorses() {
    return horses;
}

如果使用Map值,请不要忘记删除var

<f:selectItems value="#{raceController.selectedRace.horses}" />

地图的键成为选项标签,地图的值成为选项值。


对具体问题

无关HashMap本质上是无序的。如果要按插入顺序显示下拉项,请使用LinkedHashMap