Spring MVC 3.0: How do I bind to a persistent object
I'm working with Spring MVC and I'd like it to bind a a persistent object from the database, but I cannot figure out how I can set my code to make a call to the DB before binding. For example, I'm trying to update a "BenefitType" object to the database, however, I want it to get the object fromthe database, not create a new one so I do not开发者_高级运维 have to update all the fields.
@RequestMapping("/save")
public String save(@ModelAttribute("item") BenefitType benefitType, BindingResult result)
{
...check for errors
...save, etc.
}
There are several options:
In the simpliest case when your object has only simple properties you can bind all its properties to the form fields (
hidden
if necessary), and get a fully bound object after submit. Complex properties also can be bound to the form fields usingPropertyEditor
s.You may also use session to store your object between
GET
andPOST
requests. Spring 3 faciliates this approach with@SessionAttributes
annotation (from the Petclinic sample):@Controller @RequestMapping("/owners/*/pets/{petId}/edit") @SessionAttributes("pet") // Specify attributes to be stored in the session public class EditPetForm { ... @InitBinder public void setAllowedFields(WebDataBinder dataBinder) { // Disallow binding of sensitive fields - user can't override // values from the session dataBinder.setDisallowedFields("id"); } @RequestMapping(method = RequestMethod.GET) public String setupForm(@PathVariable("petId") int petId, Model model) { Pet pet = this.clinic.loadPet(petId); model.addAttribute("pet", pet); // Put attribute into session return "pets/form"; } @RequestMapping(method = { RequestMethod.PUT, RequestMethod.POST }) public String processSubmit(@ModelAttribute("pet") Pet pet, BindingResult result, SessionStatus status) { new PetValidator().validate(pet, result); if (result.hasErrors()) { return "pets/form"; } else { this.clinic.storePet(pet); // Clean the session attribute after successful submit status.setComplete(); return "redirect:/owners/" + pet.getOwner().getId(); } } }
However this approach may cause problems if several instances of the form are open simultaneously in the same session.
So, the most reliable approach for the complex cases is to create a separate object for storing form fields and merge changes from that object into persistent object manually.
So I ended up resolving this by annotating a method with a @ModelAttribute of the same name in the class. Spring builds the model first before executing the request mapping:
@ModelAttribute("item")
BenefitType getBenefitType(@RequestParam("id") String id) {
// return benefit type
}
While it is possible that your domain model is so simple that you can bind UI objects directly to data model objects, it is more likely that this is not so, in which case I would highly recommend you design a class specifically for form binding, then translate between it and domain objects in your controller.
I'm a little confused. I think you're actually talking about an update workflow?
You need two @RequestMappings, one for GET and one for POST:
@RequestMapping(value="/update/{id}", method=RequestMethod.GET)
public String getSave(ModelMap model, @PathVariable Long id)
{
model.putAttribute("item", benefitDao.findById(id));
return "view";
}
then on the POST actually update the field.
In you example above, your @ModelAttribute should already be populated with a method like the above method, and the properties be bound using something like JSTL or Spring tabglibs in conjunction with the form backing object.
You may also want to look at InitBinder depending on your use case.
精彩评论