Код: Выделить всё
user.nameЯ улавливаю исключение DataIntegrityViolationException в своем глобальном обработчике:
Код: Выделить всё
@ExceptionHandler(DataIntegrityViolationException.class)
public ResponseEntity handle(DataIntegrityViolationException ex) {
ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.UNPROCESSABLE_CONTENT, ex.getMessage());
return ResponseEntity.unprocessableContent().body(problemDetail);
}
Код: Выделить всё
{
"detail": "could not execute statement [ОШИБКА: повторяющееся значение ключа нарушает ограничение уникальности \"user_name_key\"\n Подробности: Ключ \"(name)=(jack)\" уже существует.] [insert into \"user\" (name,password,id) values (?,?,?)]; SQL [insert into \"user\" (name,password,id) values (?,?,?)]; constraint [null]",
"instance": "/api/admin/users",
"status": 422,
"title": "Unprocessable Content"
}
Что посоветуете? Вручную проверять его в моем сервисе и выбрасывать исключение вручную? Но тогда мне пришлось бы вручную синхронизировать ограничения БД и мою логику проверки. Например, если есть новый столбец UNIQUE, мне придется обновить и перестроить службу. Выглядит неоптимально.
Клод Сонет предложил следующее:
Код: Выделить всё
private String resolveDetail(DataIntegrityViolationException ex) {
if (ex.getCause() instanceof ConstraintViolationException cve) {
return switch (cve.getSQLState()) {
case "23505" -> resolveUniqueViolation(cve.getConstraintName());
case "23503" -> "Operation violates a referential integrity constraint";
case "23502" -> "A required field is missing";
case "23514" -> "A value failed a check constraint";
default -> "A database constraint was violated";
};
}
return "Data integrity violation";
}
private String resolveUniqueViolation(String constraintName) {
return appProperties.getConstraintMessages()
.getOrDefault(constraintName, "A unique constraint was violated");
}
Код: Выделить всё
app:
constraint-messages:
user_name_key: "Username is already taken"
Я могу это сделать:
Код: Выделить всё
@ExceptionHandler(ConstraintViolationException.class)
public ResponseEntity handle(ConstraintViolationException ex) {
String message = String.format("%s constraint violation", ex.getKind());
ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.UNPROCESSABLE_CONTENT, message);
return ResponseEntity.unprocessableContent().body(problemDetail);
}
Код: Выделить всё
{
"detail": "UNIQUE constraint violation",
"instance": "/api/admin/users",
"status": 422,
"title": "Unprocessable Content"
}
Код: Выделить всё
ConstraintViolationException