h: selectManyCheckbox с omnifaces.SelectItemsConverter не выбирает элементы заранее

Я использую JSF 2.0, PrimeFaces и OmniFaces.

У меня есть 2 диалога с <h:selectManyCheckbox>. Первый диалог создает новый Course:

введите здесь описание изображения

Disciplina представлены как:

<h:selectManyCheckbox id="disciplinas" 
    value="#{cursoMBean.listaDisciplinasDoCurso}"
    converter="omnifaces.SelectItemsConverter">
    <f:selectItems value="#{cursoMBean.listaTodasDisciplinas}"
        var="disciplina" itemValue="#{disciplina}"
        itemLabel="#{disciplina.nome}" />
</h:selectManyCheckbox>

Это прекрасно работает. Когда я выбираю некоторые дисциплины и отправляю форму, то новые Course с выбранными Discipline правильно вставляются в БД.

Однако, когда я пытаюсь получить существующий Course из БД, сохраненные Discipline не выбираются заранее.

введите здесь описание изображения

Код тот же:

<h:selectManyCheckbox id="disciplinas" 
    value="#{cursoMBean.listaDisciplinasDoCurso}"
    converter="omnifaces.SelectItemsConverter">
    <f:selectItems value="#{cursoMBean.listaTodasDisciplinas}"
        var="disciplina" itemValue="#{disciplina}"
        itemLabel="#{disciplina.nome}" />
</h:selectManyCheckbox>

Вот поддерживающий компонент:

private ArrayList<Disciplina> listaTodasDisciplinas;
private ArrayList<Disciplina> listaDisciplinasDoCurso;

public CursoMBean() {
    if (listaTodasDisciplinas == null) {
        listaTodasDisciplinas = controleDisciplina.consulta();
    }

    if (listaDisciplinasDoCurso == null) {
        listaDisciplinasDoCurso = new ArrayList<Disciplina>();
    }
}

// When user selects one Course to edit, this method is called:
public void setSelecionado(Curso selecionado) {
    this.selecionado = selecionado;

    if (selecionado != null) {
        listaTodasDisciplinas = controleDisciplina.consulta();
        listaDisciplinasDoCurso = controleCurso.listaDisciplinasAssociadas(selecionado);
    }
}

Вот сущность Disciplina:

public class Disciplina {

    private int id;
    private String nome;

    public Disciplina() {
    }

    public Disciplina(int id, String nome) {
        this.id = id;
        this.nome = nome;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        if (!(nome.isEmpty() || nome == " " || nome == "  ")){
            this.nome = nome;
        }
    }

}

Чем это вызвано и как я могу это решить?


person Paladini    schedule 19.11.2013    source источник
comment
Не могли бы вы также показать код вашего класса сущностей (Disciplina)?   -  person ppawel    schedule 19.11.2013
comment
Конечно, подождите, я обновлю вопрос   -  person Paladini    schedule 19.11.2013


Ответы (1)


По умолчанию SelectItemsConverter полагается на toString() сущности для соответствия выбранным элементам. Однако ваша сущность не имеет реализованного toString() и, таким образом, полагается на результат fqn@hashcode по умолчанию, который отличается при создании двух физически разных экземпляров Disciplina, даже если они имеют одинаковое значение.

По сути, у вас есть 2 варианта, которые также указаны в SelectItemsConverter витрине и javadoc:

  1. Реализуйте метод toString, который однозначно идентифицирует объект и имеет смысл в качестве идентификатора. Например,

    @Override
    public String toString() {
        return String.format("%s[id=%d]", getClass().getSimpleName(), getId());
    }
    

    (обратите внимание, что этот toString() разработан таким образом, что вы можете легко хранить его в абстрактном базовом классе всех ваших сущностей, так что вам не нужно копировать и вставлять одно и то же по всем вашим сущностям)

  2. Или, если реализация такого toString() по какой-то причине невозможна (например, полагаясь на сгенерированные классы, которые нельзя изменить впоследствии (ни шаблон генератора)), то расширьте преобразователь следующим образом:

    @FacesConverter("disciplinaSelectItemsConverter")
    public class DisciplinaSelectItemsConverter extends SelectItemsConverter {
    
        @Override
        public String getAsString(FacesContext context, UIComponent component, Object value) {
            Integer id = (value instanceof Disciplina) ? ((Disciplina) value).getId() : null;
            return (id != null) ? String.valueOf(id) : null;
        }
    
    }
    

    (примечание: вам действительно следует использовать Integer вместо int в качестве идентификатора, int не может быть null, что является правильным способом представления совершенно новой и несохраняемой сущности)

    И используйте его следующим образом

    <h:selectManyCheckbox ... converter="disciplinaSelectItemsConverter">
    
person BalusC    schedule 19.11.2013
comment
Еще раз спасибо BalusC! Я решил эту проблему сегодня утром. Я сделал быстрое исправление, и теперь оно работает, но это именно то, что вы делаете, но его сложнее реализовать. Так что, опять же, ты лучший ответ :P - person Paladini; 19.11.2013