Sé libre de divulgar nuestra página y códigos en tus redes, ayúdanos a hacer crecer nuestra comunidad.
Solución:
El problema de mostrar mensajes fáciles de usar en el caso de una violación de la restricción es que el nombre de la restricción se pierde cuando Hibernate ConstraintViolationException
se está traduciendo a Spring’s DataIntegrityViolationException
.
Sin embargo, puede personalizar esta lógica de traducción. Si utiliza LocalSessionFactoryBean
para acceder a Hibernate, puede proporcionarle un SQLExceptionTranslator
(ver LocalSessionFactoryBean.jdbcExceptionTranslator
). Este traductor de excepciones puede traducir un ConstraintViolationException
en su propia clase de excepción, conservando el nombre de la restricción.
Trato DataIntegrityViolationException
en ExceptionInfoHandler
encontrar ocurrencias de restricciones de base de datos en el mensaje de causa raíz y convertirlo en un mensaje i18n a través de constraintCodeMap
:
@ControllerAdvice(annotations = RestController.class)
@Order(Ordered.HIGHEST_PRECEDENCE + 5)
public class ExceptionInfoHandler
@Autowired
private final MessageSourceAccessor messageSourceAccessor;
private static Map CONSTRAINS_I18N_MAP = Map.of(
"users_unique_email_idx", EXCEPTION_DUPLICATE_EMAIL,
"meals_unique_user_datetime_idx", EXCEPTION_DUPLICATE_DATETIME);
@ResponseStatus(value = HttpStatus.CONFLICT) // 409
@ExceptionHandler(DataIntegrityViolationException.class)
@ResponseBody
public ErrorInfo conflict(HttpServletRequest req, DataIntegrityViolationException e)
String rootMsg = ValidationUtil.getRootCause(e).getMessage();
if (rootMsg != null)
String lowerCaseMsg = rootMsg.toLowerCase();
for (Map.Entry entry : CONSTRAINS_I18N_MAP.entrySet())
if (lowerCaseMsg.contains(entry.getKey()))
return logAndGetErrorInfo(req, e, VALIDATION_ERROR, messageSourceAccessor.getMessage(entry.getValue()));
return logAndGetErrorInfo(req, e, DATA_ERROR);
...
Se puede simular en mi aplicación de capacitación Java Enterprise agregando/editando usuarios con correo duplicado o comida con fecha y hora duplicadas.
ACTUALIZAR:
Otra solución: use el manejo de excepciones basado en el controlador:
@RestController
@RequestMapping("/ajax/admin/users")
public class AdminAjaxController {
@ExceptionHandler(DataIntegrityViolationException.class)
public ResponseEntity duplicateEmailException(HttpServletRequest req, DataIntegrityViolationException e)
return exceptionInfoHandler.getErrorInfoResponseEntity(req, e, EXCEPTION_DUPLICATE_EMAIL, HttpStatus.CONFLICT);
Spring 3 proporciona dos formas de manejar esto: HandlerExceptionResolver
en su beans.xml, o @ExceptionHandler
en su controlador. Ambos hacen lo mismo: convierten la excepción en una vista para representar.
Ambos están documentados aquí.
Sección de Reseñas y Valoraciones
Si para ti ha resultado de ayuda este artículo, te agradeceríamos que lo compartas con más seniors y nos ayudes a difundir nuestro contenido.