我使用的是Spring 3.2.4,我在验证,数据绑定和类型转换方面遇到了问题: 拥有此域类
import static javax.persistence.GenerationType.SEQUENCE;
import java.util.Comparator;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Transient;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.jboss.envers.Versioned;
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
@ParsedByDiff(fieldName="language")
@Entity
@SequenceGenerator(name = "languageSeq", sequenceName = "SEQ_LANGUAGE", allocationSize=1)
@Versioned
public class Language {
public static final String D_NAME = "name";
public static final String D_NATIVE_NAME = "nativeName";
public static final String D_ORDER = "order";
private Long id;
/**
* Name of the language.
*/
private String name;
/**
* Name of the language in the language.
*/
private String nativeName;
/**
* Member state character code.
*/
private String code;
private int order;
public Language(){
}
@Id
@GeneratedValue(strategy = SEQUENCE, generator = "languageSeq")
public Long getId(){
return id;
}
public void setId(Long newVal){
id = newVal;
}
@ParsedByDiff(fieldName="language")
public String getName(){
return name;
}
public void setName(String newVal){
name = newVal;
}
/**
* @return the nativeName
*/
@Column(name="NATIVE_NAME")
public String getNativeName() {
return nativeName;
}
/**
* @return the order
*/
@Column(name="LANG_ORDER")
public int getOrder() {
return order;
}
/**
* @param order the order to set
*/
public void setOrder(int order) {
this.order = order;
}
/**
* @param nativeName the nativeName to set
*/
public void setNativeName(String nativeName) {
this.nativeName = nativeName;
}
/**
* @return the code
*/
public String getCode() {
return code;
}
/**
* @param code the code to set
*/
public void setCode(String code) {
this.code = code;
}
/**
* Required to work with Spring's <code><form:select></code> tag.
*/
@Transient
public String getOptionValue() {
return id == null ? "" : id.toString();
}
/**
* Compares using id field only. Language instances are immutable objects
* so this strategy should work well.
*/
@Override
public boolean equals(Object object) {
boolean result = false;
if (this == object) {
result = true;
}
else if (object instanceof Language) {
Language language = (Language)object;
result = id.equals(language.id);
}
return result;
}
/**
* Aligned to equals method returns id field hash code.
*/
@Override
public int hashCode() {
return id.hashCode();
}
public static class LanguageWrapper {
private Language language;
public LanguageWrapper(Language language) {
this.language = language;
}
public Language getLanguage() {
return language;
}
@Override
public boolean equals(Object obj) {
return this.language.getId().equals(((LanguageWrapper)obj).getLanguage().getId());
}
@Override
public int hashCode() {
return this.getLanguage().getId().hashCode();
}
}
public static class LanguageWrapperNameComparator implements Comparator<LanguageWrapper> {
public int compare(LanguageWrapper o1, LanguageWrapper o2) {
return o1.getLanguage().getName().compareToIgnoreCase(o2.getLanguage().getName());
}
}
}
我在控制器的bind方法中注册它:
/**
*
*/
@SuppressWarnings("deprecation")
@Override
protected void initBinder(
HttpServletRequest request, ServletRequestDataBinder binder) throws Exception {
super.initBinder(request, binder);
binder.registerCustomEditor(Language.class, "language", new DomainObjectPropertyEditor<Language>(new DomainObjectConverter<Language>() {
@Override public Long getId(Language object) { return object.getId(); }
@Override public Language getObject(Long id) { return languageService.findById(id); }
}));
}
和DomainObjectPropertyEditor类
public class DomainObjectPropertyEditor<T> extends PropertyEditorSupport {
private DomainObjectConverter<T> domainObjectConverter;
/**
* Forces clients to provide proper converter.
* @param domainObjectConverter
*/
public DomainObjectPropertyEditor(DomainObjectConverter<T> domainObjectConverter) {
this.domainObjectConverter = domainObjectConverter;
}
@Override
public String getAsText() {
@SuppressWarnings("unchecked")
T object = (T)getValue();
if (object == null) {
return super.getAsText();
}
return String.valueOf(domainObjectConverter.getId(object));
}
@Override
public void setAsText(String text) throws IllegalArgumentException {
T object = null;
if (text != null && !text.isEmpty())
object = domainObjectConverter.getObject(Long.valueOf(text));
setValue(object);
}
}
并在JSP中:
<form:select path="language" >
<c:forEach items="${languageList}" var="language">
<form:option value="${language}">${language.nativeName} (${language.code})</form:option>
</c:forEach>
</form:select>
提交页面时出现此错误:
调试时,这是方法
的BindException错误的值 protected final ModelAndView showForm(
HttpServletRequest request, BindException errors, String viewName, Map controlModel)
throws Exception {
...
}
org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'command' on field 'language': rejected value [com.domain.Language@1]; codes [typeMismatch.command.language,typeMismatch.language,typeMismatch.com.domain.Language,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [command.language,language]; arguments []; default message [language]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'com.domain.Language' for property 'language'; nested exception is java.lang.IllegalStateException:
Cannot convert value of type [java.lang.String] to required type [com.domain.Language] for property 'language': no matching editors or conversion strategy found]