Me enfrenta el mismo problema, pero en mi caso, uno o varios campos se pueden duplicar (nombre de usuario o correo electrónico). Por lo tanto, el org.hibernate.exception.ConstraintViolationException
no es lo suficientemente específico para decir si el nombre de usuario o el correo electrónico provocaron que se lanzara esta excepción y qué mensaje mostrar en consecuencia.
Acabo de mirar danny.lesnik's answer pero no es genial, ya que simplemente redirige a una página "dedicada". Asumir que simplemente redirigir a la página en la que estaba el usuario evitaría la creación de una página nueva que diría. Sin embargo, supongo que ya tiene un Spring validator haciendo algún trabajo de validación de formularios. Es por eso que en mi caso decidí simplemente hacer mis comprobaciones de duplicación de campos (nombre de usuario y correo electrónico) en el mismo lugar (en el Validador). Parece una solución más adecuada, consistente (ubicada con el resto de la validación) y más limpia.
Aquí hay un código para ilustrar:
Mi controlador
@Controller
public class WebController {
@Autowired
private UserServiceImpl userService;
@Autowired
private CustomUserDetailsValidator customUserDetailsValidator;
...
@RequestMapping(value = "/login/create-account", method = RequestMethod.POST)
public String createAccount(@ModelAttribute("user") CustomUserDetails user, BindingResult result, Model model, SessionStatus status) {
customUserDetailsValidator.validate(user, result);
if(result.hasErrors()){
model.addAttribute("user", user);
// Print the errors to the console - FIXME: log error instead
System.out.println("Validation errors:");
for (FieldError error : result.getFieldErrors()) {
System.out.println(error.getField() + " - " + error.getDefaultMessage());
}
return "login/create-account";
}
else{
userService.registerUser(user);
return "redirect:/login/create-account-success";
}
}
...
}
Mi Validador
public class CustomUserDetailsValidator implements Validator {
@Autowired
private UserServiceImpl userService;
...
@Override
public void validate(Object target, Errors errors) {
// some simple validations
// and here some complex validation (is username or email used duplicated?)
if(errors.getAllErrors().size() == 0){
if (userService.doesUsernameAlreadyExist(user.getUsername()))
errors.rejectValue(usernameFieldName, "duplicate.username","username already exists");
if (userService.doesEmailAlreadyExist(user.getEmail()))
errors.rejectValue(emailFieldName, "duplicate.email","email already exists");
}
}
}
estoy seguro si esa es la mejor manera de hacer esto, pero pensé que mi solución sería permitir más extensión (puede agregar varias verificaciones en cualquier otra restricción).
Espero que ayude a los demás y también sería interesante obtener más pensamientos de los desarrolladores sobre esta solución.
+1 y gracias !! – Gabber