Your method in your (@)Controller class is not that efficient. You don't want to (manually) retrieve the object and copy all the fields, relationships etc. over to it. Next to that with complex objects you will sooner or alter run into big trouble.
What you want is on your first method (the GET for showing the form) retrieve the user and store it in the session using @SessionAttributes
. Next you want an @InitBinder
annotated method to set your validator on the WebDataBinder
so that spring will do the validation. This will leave your updateFromForm
method nice and clean.
@Controller
@RequestMapping("/edit/{id}")
@SessionAttributes("student")
public EditStudentController
@Autowired
private StudentFormValidator validator;
@Autowired
private StudentRepository studentRep;
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.setValidator(validator);
}
@RequestMapping(method=RequestMethod.GET)
public String showUpdateForm(Model model) {
model.addObject("student", studentRep.secureFind(id));
return "students/form";
}
@RequestMapping(method=RequestMethod.POST)
public String public String updateFromForm(@Valid @ModelAttribute Student student, BindingResult result, RedirectAttributes redirectAttributes, SessionStatus status) {
// Optionally you could check the ids if they are the same.
if (result.hasErrors()) {
return "students/form";
}
redirectAttributes.addFlashAttribute("message", "?p?t???? p??s????!");
studentRep.save(student);
status.setComplete(); // Will remove the student from the session
return "redirect:/students/list";
}
}
You will need to add the SessionStatus
attribute to the method and mark the processing complete, so that Spring can cleanup your model from the session.
This way you don't have to copy around objects, etc. and Spring will do all the heave lifting and all your fields/relations will be properly set.