Saltar al contenido

¿Cómo manejar DataIntegrityViolationException en Spring?

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 ExceptionInfoHandlerencontrar 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.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *