Spring MVC 3.0: Wie kann ich auf ein persistentes Objekt binden
-
01-10-2019 - |
Frage
Ich bin mit Spring MVC arbeiten, und ich möchte es ein ein persistentes Objekt aus der Datenbank zu binden, aber ich kann nicht herausfinden, wie ich meinen Code einstellen, um einen Anruf an die DB zu machen, bevor die Bindung. Zum Beispiel versuche ich ein „BenefitType“ Objekt in die Datenbank zu aktualisieren, aber ich will es die Objekt fromthe Datenbank erhalten, nicht einen neuen erstellen, damit ich alle die Felder nicht aktualisieren.
@RequestMapping("/save")
public String save(@ModelAttribute("item") BenefitType benefitType, BindingResult result)
{
...check for errors
...save, etc.
}
Lösung 2
So endete ich die Lösung dieses oben durch ein Verfahren mit einem @ModelAttribute mit dem gleichen Namen in der Klasse mit Anmerkungen versehen. Frühling baut das Modell zuerst, bevor die Anforderung Mapping ausführen:
@ModelAttribute("item")
BenefitType getBenefitType(@RequestParam("id") String id) {
// return benefit type
}
Andere Tipps
Es gibt mehrere Möglichkeiten:
-
Im einfachstenen Fall, wenn Ihr Objekt hat nur einfache Eigenschaften, die Sie alle seine Eigenschaften auf die Formularfelder binden können (
hidden
falls erforderlich), und ein vollständig gebundenes Objekt nach einreichen. Komplexe Eigenschaften können auch auf die Formularfelder mitPropertyEditor
s gebunden werden. -
Sie können auch Sitzung für das Objekt zwischen
GET
undPOST
Anfragen zu speichern. Frühling 3 faciliates diesen Ansatz mit@SessionAttributes
Annotation (aus der Petclinic Probe ):@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(); } } }
Doch dieser Ansatz kann zu Problemen führen, wenn mehrere Instanzen des Formulars geöffnet sind gleichzeitig in der gleichen Sitzung.
-
Also, der zuverlässigste Ansatz für die komplexen Fälle ist ein separates Objekt zu erstellen, zum Speichern von Formularfeldern und merge Änderungen von diesem Objekt in persistentes Objekt manuell.
Während es möglich ist, dass Ihr Domain-Modell so einfach ist, dass Sie binden können UI direkt an Datenmodell Objekte Objekte, ist es wahrscheinlicher, dass dies nicht so ist, wobei in diesem Fall würde ich Sie entwerfen eine Klasse speziell für Form sehr empfehlen Bindung, dann übersetzt zwischen ihm und Domain-Objekten in Ihrem Controller.
Ich bin ein wenig verwirrt. Ich glaube, Sie sprechen tatsächlich zu einem Update-Workflow?
Sie müssen zwei @RequestMappings, einen für GET und einen für POST:
@RequestMapping(value="/update/{id}", method=RequestMethod.GET)
public String getSave(ModelMap model, @PathVariable Long id)
{
model.putAttribute("item", benefitDao.findById(id));
return "view";
}
dann auf der POST das Feld tatsächlich aktualisieren.
Sie obiges Beispiel Ihre @ModelAttribute sollten bereits mit einem Verfahren wie das oben beschriebene Verfahren aufgefüllt werden, und die Eigenschaften mit dem Formular Trägerobjekt mit so etwas wie JSTL oder Frühling tabglibs in Verbindung gebunden sein.
Sie können auch auf InitBinder je nach Anwendungsfall.