我对Spring中的格式化程序有疑问。
我的选择框有一个Formatter,例如:
public class SportTypeFormatter implements Formatter<SportType> {
@Autowired
private SportTypeRepository sportTypeRepository;
@Override
public String print(SportType sportType, Locale locale) {
return String.valueOf(sportType.getTypeId());
}
@Override
public SportType parse(String sportTypeId, Locale locale) throws ParseException {
return sportTypeRepository.findSportTypeByTypeId(Long.valueOf(sportTypeId));
}
}
在百里香的像这样:
<select class="form-control" name="sportTypeId" th:field="*{person.sport.sportType}">
<option th:each="spoType : ${allSportTypes}" th:value="${spoType.typeId}" th:selected="${spoType.typeId == person.sport.sportType}" th:text="#{${'login.sport.sportType.' + spo.typeId}}" >Sporttype</option>
</select>
这很简单,因为我只需要一个值(id),而且我会选择选择框。
但是,如果我需要两个值,那该怎么办?
建议我有电子邮件,我需要id和值(邮件地址)。我可以为电子邮件构建Formatter,但我没有机会同时传输电子邮件和id。
在打印方法中我可以这样:
@Override
public String print(Email email, Locale locale) {
return email.getId() + email.getEmail();
}
在百里香中。
<input id="email" type="text" class="form-control" th:field="*{{person.email}}" th:placeholder="#{login.email}" />
但是用户可以看到id。
如果我执行绑定“标准”Spring方式,我会得到以下异常(这就是我使用格式化程序的原因):
{timestamp=Wed Dec 10 11:14:47 CET 2014, status=400, error=Bad Request, exception=org.springframework.validation.BindException,
errors=[Field error in object 'person' on field 'email': rejected value [com.sample.persistence.user.model.Email@0];
codes [typeMismatch.person.email,typeMismatch.person.institutionEmployees.email,
typeMismatch.email,typeMismatch.email,
typeMismatch.email,typeMismatch.com.sample.persistence.user.model.Email,typeMismatch];
arguments [org.springframework.context.support.DefaultMessageSourceResolvable:
codes [person.email,email];
arguments [];
default message [email]];
default message [Failed to convert property value of type 'com.sample.persistence.user.model.Email'
to required type 'com.sample.persistence.user.model.Email'
for property 'email';
nested exception is org.springframework.core.convert.ConversionFailedException:
Failed to convert from type com.sample.persistence.user.model.Email
to type @javax.persistence.OneToOne @javax.persistence.JoinColumn @com.google.gson.annotations.Expose
com.sample.persistence.user.model.Email for value
'com.sample.persistence.user.model.Email@0';
nested exception is org.springframework.dao.InvalidDataAccessApiUsageException:
Provided id of the wrong type for class com.sample.persistence.user.model.Email.
Expected: class java.lang.Long, got class java.lang.String;
nested exception is java.lang.IllegalArgumentException:
Provided id of the wrong type for class com.sample.persistence.user.model.Email.
Expected: class java.lang.Long, got class java.lang.String]],
message=Validation failed for object='person'. Error count: 1, path=/manageUsers/Ab-Soul/edit}
欢迎任何建议。
提前致谢。
1。编辑:
控制器方法
@RequestMapping(value = "/{login}/edit", method = RequestMethod.GET)
public ModelAndView editUserByLogin(@PathVariable("login") final String login) {
final User currentUser = UserRepository.findPersonByLogin(login);
ModelAndView mav = new ModelAndView(URL_EDIT_USER);
mav.addObject(MODEL_USER, currentUser);
return mav;
}
该场景,'admin'获取所有当前用户的列表,如果他点击该表,将使用他点击的用户的名称调用requestmapping-method。
电子邮件类:
@Entity(name="Email")
public class Email implements Serializable
{
private static final long serialVersionUID = 6891079722082340011L;
@Id()
@GeneratedValue(strategy=GenerationType.AUTO)
@Expose
protected Long emailId;
@Expose
protected String value;
//getter/setter
@Override
public boolean equals(Object obj)
{
if(obj instanceof Email){
return value.equals(((Email) obj).getValue());
}
return false;
}
@Override
public int hashCode()
{
return value.hashCode();
}
}
2。编辑:
现在我已将child的电子邮件字段更改为emailChild
org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'person' on field 'child[0].emailChild':
rejected value [com.sample.persistence.user.model.Email@0];
codes [typeMismatch.person.child[0].emailChild,
typeMismatch.person.child.emailChild,
typeMismatch.child[0].emailChild,
typeMismatch.child.emailChild,
typeMismatch.emailChild,
typeMismatch.com.sample.persistence.user.model.Email,typeMismatch];
arguments [org.springframework.context.support.DefaultMessageSourceResolvable:
codes [person.child[0].emailChild,child[0].emailChild];
arguments [];
default message [child[0].emailChild]];
default message [Failed to convert property value of type 'com.sample.persistence.user.model.Email' to required type 'com.sample.persistence.user.model.Email'
for property 'child[0].emailChild';
nested exception is org.springframework.core.convert.ConversionFailedException: Failed to convert from type com.sample.persistence.user.model.Email
to type @javax.persistence.OneToOne @javax.persistence.JoinColumn @com.google.gson.annotations.Expose com.sample.persistence.user.model.Email
for value 'com.sample.persistence.user.model.Email@0';
nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: Provided id of the wrong type for class com.sample.persistence.user.model.Email. Expected: class java.lang.Long, got class java.lang.String;
nested exception is java.lang.IllegalArgumentException: Provided id of the wrong type for class com.sample.persistence.user.model.Email. Expected: class java.lang.Long, got class java.lang.String]
第3。编辑:
为帖子添加控制器方法:
@RequestMapping(value = "/{login}/edit", method = RequestMethod.POST)
public ModelAndView updateUser(@PathVariable("login") final String login, @ModelAttribute(MODEL_USER) final Person person, BindingResult bindingResult, final Model model) {
Person repositoryPerson = personRepository.findPersonByLogin(login);
repositoryPerson = repositoryPerson.updateWith(person);
manageUserService.updatePerson(repositoryPerson);
model.asMap().clear();
return new ModelAndView("redirect:" + URL_USERS_OVERVIEW, MODEL, model);
}
答案 0 :(得分:0)
我已经回答了我自己的问题。
我们应该记住
编辑过程只发生问题,因此我在数据库中有一个有效的电子邮件对象,使用有效的子对象绑定,并使用有效的用户对象进行绑定。
我决定使用以下实现构建EmailFormatter
:
public class EmailFormatter implements Formatter<Email> {
@Override
public String print(Email email, Locale locale) {
return email.getValue();
}
@Override
public Email parse(String mailAddress, Locale locale) throws ParseException {
return new Email(mailAddress);
}
}
有了这个,我在我的Child-Instance中获得了一个新的Email-Object(没有id)。现在我在有效的子对象中有一个有效的电子邮件对象。看一下后方法:
@RequestMapping(value = "/{login}/edit", method = RequestMethod.POST)
public ModelAndView updateUser(@PathVariable("login") final String login, @ModelAttribute(MODEL_USER) final Person person, BindingResult bindingResult, final Model model) {
Person repositoryPerson = personRepository.findPersonByLogin(login);
repositoryPerson = repositoryPerson.updateWith(person);
manageUserService.updatePerson(repositoryPerson);
model.asMap().clear();
return new ModelAndView("redirect:" + URL_USERS_OVERVIEW, MODEL, model);
}
此时我有来自用户的登录名,我得到了#34; old&#34;来自db的(有效)user-Object。我写了一个&#34; merge&#34;方法,我给'老'&#34; user对象修改后的用户对象。
在这里,我可以获取带有ID的旧电子邮件对象,并将电子邮件地址设置为:
this.emailChild.setValue(modifiedChild.getemailChild().getValue());
在此之后我看看这个解决方案,我注意到这很简单。
但是如果绑定问题是由一个&#34;复杂的&#34; (然后,多一个相关领域)对象,我认为,你会更好地解决PatrickLC建议的解决方案:
@InitBinder
public void setAllowedFields(WebDataBinder dataBinder) {
dataBinder.setDisallowedFields("emailId");
}