Как обработать исключение DataIntegrityViolationException весной? - PullRequest
8 голосов
/ 21 января 2010

Мне нужно показать пользовательские сообщения в моем приложении Spring 3.0. У меня есть база данных с Hibernate и есть несколько ограничений. У меня есть сомнения в том, как правильно обрабатывать DataIntegrityViolationException. Интересно, есть ли способ сопоставить исключение с набором сообщений в файле свойств, как это возможно при проверке ограничений. Могу ли я обработать это каким-либо образом автоматически или мне нужно перехватить это исключение в каждом контроллере?

Ответы [ 3 ]

9 голосов
/ 21 января 2010

Проблема с отображением удобных для пользователя сообщений в случае нарушения ограничения заключается в том, что имя ограничения теряется при переводе ConstraintViolationException Hibernate в DataIntegrityViolationException.

Spring.

Однако вы можете настроить эту логику перевода. Если вы используете LocalSessionFactoryBean для доступа к Hibernate, вы можете предоставить ему пользовательский SQLExceptionTranslator (см. LocalSessionFactoryBean.jdbcExceptionTranslator). Этот переводчик исключений может преобразовать ConstraintViolationException в ваш собственный класс исключений, сохранив имя ограничения.

4 голосов
/ 21 января 2010

Spring 3 предоставляет два способа обработки этого - HandlerExceptionResolver в вашем beans.xml или @ExceptionHandler в вашем контроллере. Они оба делают одно и то же - они превращают исключение в представление для визуализации.

Оба задокументированы здесь .

3 голосов
/ 23 февраля 2017

Я обрабатываю DataIntegrityViolationException в ExceptionInfoHandler, нахожу вхождения ограничений DB в сообщении первопричины и преобразую его в сообщение i18n через constraintCodeMap:

@ControllerAdvice(annotations = RestController.class)
@Order(Ordered.HIGHEST_PRECEDENCE + 5)
public class ExceptionInfoHandler {

  @Autowired
  private MessageSource messageSource;

  private static Map<String, String> constraintCodeMap = new HashMap<String, String>() {
    {
        put("users_unique_email_idx", "exception.users.duplicate_email");
        put("meals_unique_user_datetime_idx", "exception.meals.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) {
        Optional<Map.Entry<String, String>> entry = constraintCodeMap.entrySet().stream()
                .filter((it) -> rootMsg.contains(it.getKey()))
                .findAny();
        if (entry.isPresent()) {
            e=new DataIntegrityViolationException(
                  messageSource.getMessage(entry.get().getValue(), null, LocaleContextHolder.getLocale());
        }
    }
    return new ErrorInfo(req, e);
  }
  ...
}

Можно смоделировать в моем учебном приложении Java Enterprise , добавив / отредактировав пользователя с дубликатами почты или еды с дубликатом dateTime.

UPDATE

Другое решение: используйте Обработка исключений на основе контроллера :

@RestController
@RequestMapping("/ajax/admin/users")
public class AdminAjaxController {

    @ExceptionHandler(DataIntegrityViolationException.class)
    public ResponseEntity<ErrorInfo> duplicateEmailException(HttpServletRequest req, DataIntegrityViolationException e) {
        return exceptionInfoHandler.getErrorInfoResponseEntity(req, e, EXCEPTION_DUPLICATE_EMAIL, HttpStatus.CONFLICT);
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...