我正在使用JSF 2.0,PrimeFaces和OmniFaces。
我有<h:selectManyCheckbox>
的2个对话框。第一个对话框创建一个新的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>
这是支持bean:
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;
}
}
}
这是如何引起的?如何解决?
答案 0 :(得分:2)
默认情况下,SelectItemsConverter
依赖于实体的toString()
来匹配所选项目。但是,您的实体没有实现toString()
,因此依赖于默认fqn@hashcode
结果,即使它们具有相同的值,当创建两个物理上不同的Disciplina
实例时,结果也不相同
您基本上有2个选项,也在SelectItemsConverter
showcase和javadoc中暗示:
实现唯一标识实体的toString
方法,并将其作为标识符。例如,
@Override
public String toString() {
return String.format("%s[id=%d]", getClass().getSimpleName(), getId());
}
(请注意,此toString()
的设计使您可以轻松地将其保存在所有实体的抽象基类中,这样您就不需要在所有实体上对其进行复制。
或者,如果由于某种原因实现这样的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
作为ID,int
不能是null
,这是表示身份的正确方法全新且无人值守的实体)
并按如下方式使用
<h:selectManyCheckbox ... converter="disciplinaSelectItemsConverter">