如何在Spring中处理DataIntegrityViolationException?

Jav*_*avi 8 java spring exception-handling spring-mvc

我需要在Spring 3.0应用程序中显示自定义消息.我有一个Hibernate数据库,有几个约束.我对如何DataIntegrityViolationException以良好的方式处理有疑问.我想知道是否有一种方法可以在属性文件中使用消息集映射异常,因为它可以在约束验证中使用.我可以以任何方式自动处理它,或者我必须在每个控制器中捕获此异常吗?

axt*_*avt 9

在违反约束的情况下显示用户友好消息的问题是当Hibernate ConstraintViolationException被转换为Spring 时,约束名称会丢失DataIntegrityViolationException.

但是,您可以自定义此转换逻辑.如果您使用LocalSessionFactoryBean访问Hibernate,可以为其提供自定义SQLExceptionTranslator(请参阅参考资料LocalSessionFactoryBean.jdbcExceptionTranslator).此异常转换器可以将a ConstraintViolationException转换为您自己的异常类,同时保留约束名称.


GKi*_*lin 9

我对待DataIntegrityViolationException的ExceptionInfoHandler,在根源消息寻找DB约束出现,它通过转换成国际化的消息constraintCodeMap:

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

  @Autowired
  private final MessageSourceAccessor messageSourceAccessor;

  private static Map<String, String> 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<String, String> 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);
  }
  ...
}
Run Code Online (Sandbox Code Playgroud)

可以在我的Java Enterprise 培训应用程序中通过添加/编辑具有重复邮件或具有重复日期时间的膳食的用户来模拟。

更新:

其他解决方案:使用基于控制器的异常处理:

@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);
    }
Run Code Online (Sandbox Code Playgroud)