복붙노트

[SPRING] Spring에서 DataIntegrityViolationException을 처리하는 방법?

SPRING

Spring에서 DataIntegrityViolationException을 처리하는 방법?

Spring 3.0 애플리케이션에서 커스텀 메시지를 보여줄 필요가있다. 나는 Hibernate가있는 데이터베이스를 가지고 있으며 몇 가지 제약이있다. 나는 DataIntegrityViolationException이 좋은 방법으로 처리되어야하는 방법에 의구심이있다. 제약 조건 유효성 검사에서 가능한 것처럼 속성 파일에 설정된 메시지로 예외를 매핑하는 방법이 있는지 궁금합니다. 어떤 방식 으로든 자동으로 처리 할 수 ​​있습니까 아니면 각 컨트롤러에서이 예외를 잡아야합니까?

해결법

  1. ==============================

    1.제약 조건 위반의 경우 사용자 친화적 인 메시지를 보여주는 문제는 Hibernate의 ConstraintViolationException이 Spring의 DataIntegrityViolationException으로 변환 될 때 제약 조건 이름이 손실된다는 것이다.

    제약 조건 위반의 경우 사용자 친화적 인 메시지를 보여주는 문제는 Hibernate의 ConstraintViolationException이 Spring의 DataIntegrityViolationException으로 변환 될 때 제약 조건 이름이 손실된다는 것이다.

    그러나이 변환 논리를 사용자 정의 할 수 있습니다. LocalSessionFactoryBean을 사용하여 Hibernate에 접근하는 경우, 사용자 정의 SQLExceptionTranslator를 제공 할 수 있습니다 (LocalSessionFactoryBean.jdbcExceptionTranslator 참조). 이 예외 변환기는 제한 조건 이름을 보존하면서 ConstraintViolationException을 사용자 고유의 예외 클래스로 변환 할 수 있습니다.

  2. ==============================

    2.Spring 3은 이것을 처리하는 두 가지 방법, 즉 beans.xml의 HandlerExceptionResolver 또는 컨트롤러의 @ExceptionHandler를 제공한다. 둘 다 똑같은 일을합니다. 예외를 렌더링 할 뷰로 바꿉니다.

    Spring 3은 이것을 처리하는 두 가지 방법, 즉 beans.xml의 HandlerExceptionResolver 또는 컨트롤러의 @ExceptionHandler를 제공한다. 둘 다 똑같은 일을합니다. 예외를 렌더링 할 뷰로 바꿉니다.

    두 가지 모두 여기에 설명되어 있습니다.

  3. ==============================

    3.ExceptionInfoHandler에서 DataIntegrityViolationException을 처리하여 근본 원인 메시지에서 DB 제약 조건을 찾아 constraintCodeMap을 통해 i18n 메시지로 변환합니다.

    ExceptionInfoHandler에서 DataIntegrityViolationException을 처리하여 근본 원인 메시지에서 DB 제약 조건을 찾아 constraintCodeMap을 통해 i18n 메시지로 변환합니다.

    @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);
      }
      ...
    }
    

    중복 된 메일 또는 중복 dateTime과 함께 사용자를 추가 / 편집하여 Java Enterprise Training 애플리케이션에서 시뮬레이션 할 수 있습니다.

    최신 정보:

    다른 해결책 : 컨트롤러 기반 예외 처리 사용 :

    @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);
        }
    
  4. from https://stackoverflow.com/questions/2109476/how-to-handle-dataintegrityviolationexception-in-spring by cc-by-sa and MIT license