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" Джошуа Блоха.