I have an application written in Spring 3.0 hooked up using Hibernate to a database. I have a controller to an update form. Whenever the form is submitted, I expect the object that is shown to be updated however a new object is created with a new ID value. I've looked over the "petclinic" sample and i can't see how it is different.
POJO
public class Person
{
private int id;
@NotNull
private String name;
//getter/setter for id
//getter/setter for name
}
Controller
public class PersonUpdateController
{
//injected
private PersonService personService;
@RequestMapping(value="/person/{per开发者_运维百科sonId}/form", method=RequestMethod.POST)
public String updateForm(ModelMap modelMap, @PathVariable personId)
{
Person person = personService.getById(personId);
modelMap.addAttribute(person);
return "person/update";
}
@RequestMapping(value="/person/{personId}", method=RequestMethod.POST)
public String update(ModelMap modelMap, @Valid Person person, BindingResult bindingResult)
{
if(bindingResult.hasErrors())
{
modelMap.addAttribute(person);
return "person/update";
}
personService.save(person);
return "redirect:person/" + person.getId() + "/success";
}
}
JSP
<spring:url value="/person/${person.id}" var="action_url" />
<spring:form action="${action_url}" modelAttribute="person" method="POST">
<spring:input name="name" path="name" />
<input type="submit" value="Save" />
</spring:form>
PersonService Implementation
public class HibernatePersonService
implements PersonService
{
//injected
private SessionFactory sessionFactory;
//other methods
public void save(Person person)
{
Session session = sessionFactory.getCurrentSession();
session.saveOrUpdate(person);
}
}
Spring MVC doesn't do any magic with HTML forms. Since your form contains only one field, you get only one field populated in update method. So, you have two options:
- Pass
id
as a hidden field in the form:<spring:hidden path = "id" />
. Note that in this case you need to check possible consequences for security (what happens if malicious person changes the id). - Store
Person
in the session so that data from the form is used to update the stored object (note that it may cause interference if several instances of the form is opened in one session). That's how it's done in Petclinic:
-
@SessionAttributes("person")
public class PersonUpdateController {
...
@RequestMapping(value="/person/{personId}", method=RequestMethod.POST)
public String update(ModelMap modelMap, @Valid Person person,
BindingResult bindingResult, SessionStatus status)
{
...
personService.save(person);
status.setComplete(); // Removes person from the session after successful submit
...
}
@InitBinder
public void setAllowedFields(WebDataBinder dataBinder) {
dataBinder.setDisallowedFields("id"); // For security
}
}
精彩评论