在完成一个功能的时候遇到一个问题:
在使用h:selectOneMenu时即使已经加了<s:convertEntity>仍然报错:value is not valide.
后来google了一下,seam 的论坛上几个帖子分析的原因都是因为实体的equal方法的问题,然后在一篇国内的搏客上看到了一个解决方法:
作者
sulong 分类:
java,
程序
当你用jsf的<h:selectOneMenu />之类的控件选择实体时,小心你的实体的equals方法,否则你可能就会遇到”value is not valid”的验证错误。比如,如果你的页面里有这样一段:
<h:selectOneMenu value="#{fooAction.foo}">
<s:selectItems value="#{fooList.resultList}" var="foo" label="#{foo.name}"/>
<s:convertEntity />
</h:selectOneMenu>
你的Foo实体类的equals方法又是这样写的:
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
final Foo other = (Area) 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
延迟加载时的一个stub,那正常的对象和这个stub对比时就可能出错。对于上面的例子,getClass() != obj.getClass()
会为真,而 other.id != null 也可能为真。怎么办?改写equals方法,如下:
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!getClass().isAssignableFrom(obj.getClass()))
return false;
final Area other = (Area) obj;
if (id == null) {
if (other.getId() != null)
return false;
} else if (!id.equals(other.getId()))
return false;
return true;
}
isAssignableFrom方法对子类调用时一样为真。other.getId()时,则会初始化stub,取出id的值。
还有一种更简单的方法,那就是不要让用户选择实体,而是选择实体的id,那就没这个问题了。
原文地址:http://www.sulong.info/archives/104
我尝试了选择id 的方法,但是总是报错: identifier of an instance of xx was altered from xx to xx.
等过几天再解决一下。
另:如果实体中有需要延迟加载的属性,也可能会报这个错误。
http://www.jboss.org/index.html?module=bb&op=viewtopic&p=4127804