JSF SelectOneMenu HashMap转换器的instanceOf错误

JSF SelectOneMenu HashMap转换器的instanceOf错误,jsf,selectonemenu,Jsf,Selectonemenu,在我的实体类中,我有一个HashMap。现在我正在尝试创建一个选择这个地图,以便能够选择其中一个对象。因此,我创建了以下类: 马力转换器: @Named public class HorseConverter implements Converter{ @EJB private HorseBean bean; @Override public Object getAsObject(FacesContext context, UIComponent compon

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

马力转换器:

@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>
种族实体:

@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>

您是否重写了Horse()对象中的hashcode()和equals()

您的转换器需要覆盖equals()才能工作。如果不这样做,那么对同一个Horse()实例的两个引用将是相等的,而不是具有完全相同状态的两个独立实例。集合创建一个要比较的隐式副本,因此在本例中,堆上没有一个实例

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

如果不重写hashcode(),则hashcode对于Horse的每个实例都是不同的。这意味着您将很难找到正确的马进行比较,即使您的马在逻辑上是等价的,因为同样,您将有多个实例进行比较,以便在HashMap中找到您的马


有关更多信息,请参阅本章。

您不能在
映射
值上使用
var
。只有使用
列表
而不是
映射
时,此特定的
构造才有效

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

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

贴图的键成为选项标签,贴图的值成为选项值



与具体问题无关,
HashMap
本质上是无序的。如果要按插入顺序显示下拉列表项,请使用
LinkedHashMap

不覆盖它们将导致
验证错误:提交时值无效。OP似乎没有面临这个问题。当只显示页面时,OP已经面临问题。请注意,将调用转换器的
getAsString()
,而不是
getAsObject()
。实际上,正如BalusC所述,已经实现了一个equals和hash。编辑消息。谢谢,虽然我不确定我的书写方式是否正确,但我返回的地图来自我的RaceController,其中包含了马的对象和人们在那匹马上下注的金额。我想,如果字符串值(昵称)是键(它不是唯一的),那么您要告诉我的是,我不能使用对象作为键?重点是,您不能在地图值上使用
。如果要使用
var
,则需要例如
List
。或者,如果要使用
Map
,请删除
var
(和
itemLabel
itemlavue
)并修复映射结构,使其准确地保存所需的标签和值。