Spring MVC 如何在Spring中处理DataIntegrityViolationException?

ldxq2e6h  于 2022-11-14  发布在  Spring
关注(0)|答案(4)|浏览(178)

我需要在我的Spring3.0应用程序中显示自定义消息。我有一个使用Hibernate的数据库,并且有几个约束。我怀疑应该如何以一种好的方式处理DataIntegrityViolationException。我想知道是否有一种方法可以将异常Map到属性文件中的消息集。我可以用任何方式自动处理它吗?或者我必须在每个控制器中捕获这个异常?

nhaq1z21

nhaq1z211#

在违反约束的情况下显示用户友好消息的问题是,当Hibernate的ConstraintViolationException被转换为Spring的DataIntegrityViolationException时,约束名称会丢失。
但是,您可以自定义此转换逻辑。如果您使用LocalSessionFactoryBean访问Hibernate,则可以为其提供自定义的SQLExceptionTranslator(请参见LocalSessionFactoryBean.jdbcExceptionTranslator)。此异常转换器可以将ConstraintViolationException转换为您自己的异常类,同时保留约束名称。

bjg7j2ky

bjg7j2ky2#

我在ExceptionInfoHandler中处理DataIntegrityViolationException,在根本原因消息中找到DB约束,并通过constraintCodeMap将其转换为i18 n消息:

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

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

更新

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

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

e1xvtsh33#

Spring 3提供了两种处理方法-beans.xml中的HandlerExceptionResolver,或者控制器中的@ExceptionHandler。它们都做同样的事情-它们将异常转换成视图来呈现。
这两种情况都在此处进行了记录。

t40tm48m

t40tm48m4#

1.在你的请求体类中检查非null或非空类

public class CustomerRegisterRequestDto {
    @NotEmpty(message = "first name is empty")
    @NotNull(message = Constants.EntityValidators.FIRST_NAME_NULL)
    private String first_name;
    //other fields
    //getters and setters
}

2.然后在您的服务中检查此

ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    Validator validator = factory.getValidator();
    Set<ConstraintViolation<CustomerRegisterRequestDto>> violations = validator.validate(userDto);
    if (!violations.isEmpty()) {
        //something is wrong in request parameters
        List<String> details = new ArrayList<>();
        for (ConstraintViolation<CustomerRegisterRequestDto> violation : violations) {
            details.add(violation.getMessage());
        }
        ErrorResponse error = new ErrorResponse(Constants.ErrorResponse.REQUEST_PARAM_ERROR, details);
        return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
    }

3. Here是您的ErrorResponse类别

相关问题