牛骨文教育服务平台(让学习变的简单)
博文笔记

JSF Validation Error: Value is not valid(值无效)JSF值转换无效的两个解决办法

创建时间:2017-02-12 投稿人: 浏览次数:696

第一次在用jsf框架编写物品分类的时候,用下拉列表来选取上级分类,出现了转换错误:值无效的问题。很长一段时间自己都认为是转换器的问题,其实不是。话不多说,上代码:

前台页面的写法:

<tr>
    <td>上级目录</td>
    <td><h:selectOneMenu id="category_fk"
                        value="#{itemaddmanager.newItem.category.id}" converter="#{categoryConverterBean}" title="category">
       	    <f:selectItem itemLabel="--选择分类--" />
            <f:selectItems value="#{categoryManager.allCategory}" var="Category" itemValue="#{Category.id}" itemLabel="#{Category.name}"/>
            </h:selectOneMenu>
    </td>
</tr>

之前的Category的equals的写法:

public boolean equals(Object obj) {

        if (this == obj) {
            return true;
        }

        if (obj == null) {
            return false;
        }

        if (getClass() != obj.getClass()) {
            return false;
        }

        final Category other = (Category) obj;

        if (id == null) {

            if (other.id != null) {
                return false;
            }

        } else if (!id.equals(other.id)) {
            return false;
        }

        return true;

    }

很好,你很可能就有机会遭遇seam下这个神奇的value is not valid验证问题了。到底原因何在?原因就在于seam不仅使用了jsf还使用了hibernate,而你的equals方法没有考虑到被对比的双方可能一个是实体类,另一个可能是被hibernate动态增强过的类。JSF在客户端提交表单后,会验证客户端选中的元素是否是当初服务端给他的那些元素。所以,JSF会拿经converter得到的实体与当初的集合里的实体一一调用equals方法对比,如果找不到一个在集合中的实体与提交来的一样,就报错。如果集合里的对象是hibernate 延迟加载时的一个Category,那正常的对象和这个Category对比时就可能出错。对于上面的例子,getClass() != obj.getClass() 会为真,而 other.id != null 也可能为真。怎么办?改写equals方法,如下:

更改之后的Category的equals和hashcode的写法:

@Override
    public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((id == null) ? 0 : id.hashCode());
    result = prime * result
            + ((name == null) ? 0 : name.hashCode());
    return result;   
    }
    
    @Override
    public boolean equals(Object obj) {

        if (this == obj) {
            return true;
        }

        if (obj == null) {
            return false;
        }

        if (!getClass().isAssignableFrom(obj.getClass())) {
            return false;
        }

        final Category other = (Category) obj;

        if (id == null) {

            if (other.getId() != null) {
                return false;
            }

        } else if (!id.equals(other.getId())) {
            return false;
        }

        return true;

    }

isAssignableFrom方法对子类调用时一样为真。other.getId()时,则会初始化Category,取出id的值。

还有一种更简单的方法,那就是不要让用户选择实体,而是选择实体的id,那就没这个问题了。

用id时的converter写法

@Override
public Object getAsObject(FacesContext ctx, UIComponent component, String value) throws ConverterException {

	if (!value.equals("") && value != null) {
                String Catname = value;
		System.out.println("前台返回的实体名字" + Catname);
		Category category = categoryservice.findCategoryByName(Catname);
		System.out.println("查询到的实体:" + category.getId() + ",名字:" + category.getName());
                int categoryid = category.getId();
		return categoryid;
	}
	return null;
}


声明:该文观点仅代表作者本人,牛骨文系教育信息发布平台,牛骨文仅提供信息存储空间服务。