JSF SelectOneMenu HashMap Converter имеет неправильный экземпляр

В моем классе 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>

Похоже, ценность, которую я получаю, не является экземпляром Horse. Я проверил следующую ссылку: https://stackru.com/tags/selectonemenu/info Таким образом, похоже, что ключ автоматически используется в качестве значения. Но даже написание h.key не имеет значения.

РЕДАКТИРОВАТЬ: Вот мой хэш и равный код от сущности лошади:

@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 ответа

Решение

Вы не можете использовать var на Map значение. Этот конкретный <f:selectItems> конструкция работает только если вы используете List<Horse> вместо Map<Horse, Integer>,

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

Если вы действительно хотите использовать Mapтогда вы должны возвращать Map<String, Horse>, где String это прозвище Horse,

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

В случае использования Map значение, не забудьте удалить var:

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

Ключ карты становится меткой опции, а значение карты становится значением опции.


Не связанные с конкретной проблемой, HashMap по природе неупорядочен. Если вы хотите отобразить выпадающие элементы в порядке вставки, используйте LinkedHashMap,

Вы переопределили hashcode () и equals() в вашем объекте Horse ()?

Для работы вашего конвертера необходимо переопределить метод equals(). Если вы этого не сделаете, будут равны только две ссылки на один и тот же экземпляр Horse (), а не два отдельных экземпляра, которые имеют абсолютно одинаковое состояние. Коллекции создают неявную копию для сравнения, поэтому в этом случае у вас не будет ни одного экземпляра в куче.

Не забывайте, что аргумент в объекте equals() - Object(), а не Horse().

Если вы не переопределите hashcode (), хеш-код будет отличаться для каждого экземпляра Horse. Это означает, что вы будете изо всех сил пытаться найти правильную лошадь для сравнения, даже если ваши лошади логически эквивалентны, потому что у вас будет более одного экземпляра, который вы будете сравнивать, чтобы найти свою лошадь в вашей HashMap.

Для получения дополнительной информации см. Эту главу " Эффективная Java" Джошуа Блоха.

Другие вопросы по тегам