自定义 - ConstraintViolationException - SQL 异常
Custom - ConstraintViolationException - SQL Exception
我有一个自定义建议来处理从 REST API Error Handling 复制的控制器的异常,还有一个方法来处理 DataIntegrityViolationException:
@ExceptionHandler(DataIntegrityViolationException.class)
protected ResponseEntity<Object> handleDataIntegrityViolation(DataIntegrityViolationException ex,
WebRequest request) {
if (ex.getCause() instanceof ConstraintViolationException) {
return buildResponseEntity(new ApiError(HttpStatus.CONFLICT, "Database error", ex));
}
return buildResponseEntity(new ApiError(HttpStatus.INTERNAL_SERVER_ERROR, ex));
}
ApiError - 构造函数
public ApiError(HttpStatus status, String message, Throwable ex) {
this();
this.status = status;
this.message = message;
this.debugMessage = ex.getLocalizedMessage();
}
发生错误时,响应会显示如下消息:
"apierror": {
"status": "CONFLICT",
"message": "Database error",
"debugMessage": "could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement",
"constraintName": null
}
问题是消息没有向消费者显示真正的问题,因为真正的问题在里面 (ex.getCause().getCause().getMessage()
):
Cannot delete or update a parent row: a foreign key constraint fails
(`cup_orchestrator`.`cpo_production_cycle`, CONSTRAINT `fk_cpo_production_cycle_cpo_cycle_type1`
FOREIGN KEY (`cycle_type_id`) REFERENCES `cpo_cycle_type` (`cycle_type_id`))
我想处理这样的消息:“记录仍然有来自其他 table 的参考”;
是否有任何自定义处理程序异常以更具体的方式处理 sql 异常?
我已将 DataIntegrityViolationException 句柄更改为更具体:
@ExceptionHandler(DataIntegrityViolationException.class)
protected ResponseEntity<Object> handleDataIntegrityViolation(DataIntegrityViolationException ex,
WebRequest request) {
Throwable cause = ex.getRootCause();
if (cause instanceof SQLIntegrityConstraintViolationException) {
SQLIntegrityConstraintViolationException consEx = (SQLIntegrityConstraintViolationException) cause;
String message = "";
String constraint = "";
HttpStatus httpStatus = null;
if (consEx.getMessage().contains("UNIQUE")) {
message = "Cannot enter the same record twice";
constraint = "DUPLICATED_RECORD";
httpStatus = HttpStatus.CONFLICT;
} else if (consEx.getMessage().contains("foreign key constraint")) {
message = "Record still have reference from other table";
constraint = "USED_RECORD";
httpStatus = HttpStatus.UNPROCESSABLE_ENTITY;
}
return buildResponseEntity(new ApiError(httpStatus, message, consEx.getMessage(), constraint));
} else if (ex.getCause() instanceof ConstraintViolationException) {
return buildResponseEntity(new ApiError(HttpStatus.CONFLICT, "Database error", ex));
}
return buildResponseEntity(new ApiError(HttpStatus.INTERNAL_SERVER_ERROR, ex));
}
并且我在 ApiError class 上创建了一个约束属性和一个用于接收的构造函数:
public ApiError(HttpStatus status, String message, String debugMessage, String constraint) {
this.status = status;
this.message = message;
this.debugMessage = debugMessage;
this.constraint = constraint;
}
在 React 应用程序上将创建一个包到这个约束:
DUPLICATED_RECORD
USED_RECORD
我有一个自定义建议来处理从 REST API Error Handling 复制的控制器的异常,还有一个方法来处理 DataIntegrityViolationException:
@ExceptionHandler(DataIntegrityViolationException.class)
protected ResponseEntity<Object> handleDataIntegrityViolation(DataIntegrityViolationException ex,
WebRequest request) {
if (ex.getCause() instanceof ConstraintViolationException) {
return buildResponseEntity(new ApiError(HttpStatus.CONFLICT, "Database error", ex));
}
return buildResponseEntity(new ApiError(HttpStatus.INTERNAL_SERVER_ERROR, ex));
}
ApiError - 构造函数
public ApiError(HttpStatus status, String message, Throwable ex) {
this();
this.status = status;
this.message = message;
this.debugMessage = ex.getLocalizedMessage();
}
发生错误时,响应会显示如下消息:
"apierror": {
"status": "CONFLICT",
"message": "Database error",
"debugMessage": "could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement",
"constraintName": null
}
问题是消息没有向消费者显示真正的问题,因为真正的问题在里面 (ex.getCause().getCause().getMessage()
):
Cannot delete or update a parent row: a foreign key constraint fails
(`cup_orchestrator`.`cpo_production_cycle`, CONSTRAINT `fk_cpo_production_cycle_cpo_cycle_type1`
FOREIGN KEY (`cycle_type_id`) REFERENCES `cpo_cycle_type` (`cycle_type_id`))
我想处理这样的消息:“记录仍然有来自其他 table 的参考”;
是否有任何自定义处理程序异常以更具体的方式处理 sql 异常?
我已将 DataIntegrityViolationException 句柄更改为更具体:
@ExceptionHandler(DataIntegrityViolationException.class)
protected ResponseEntity<Object> handleDataIntegrityViolation(DataIntegrityViolationException ex,
WebRequest request) {
Throwable cause = ex.getRootCause();
if (cause instanceof SQLIntegrityConstraintViolationException) {
SQLIntegrityConstraintViolationException consEx = (SQLIntegrityConstraintViolationException) cause;
String message = "";
String constraint = "";
HttpStatus httpStatus = null;
if (consEx.getMessage().contains("UNIQUE")) {
message = "Cannot enter the same record twice";
constraint = "DUPLICATED_RECORD";
httpStatus = HttpStatus.CONFLICT;
} else if (consEx.getMessage().contains("foreign key constraint")) {
message = "Record still have reference from other table";
constraint = "USED_RECORD";
httpStatus = HttpStatus.UNPROCESSABLE_ENTITY;
}
return buildResponseEntity(new ApiError(httpStatus, message, consEx.getMessage(), constraint));
} else if (ex.getCause() instanceof ConstraintViolationException) {
return buildResponseEntity(new ApiError(HttpStatus.CONFLICT, "Database error", ex));
}
return buildResponseEntity(new ApiError(HttpStatus.INTERNAL_SERVER_ERROR, ex));
}
并且我在 ApiError class 上创建了一个约束属性和一个用于接收的构造函数:
public ApiError(HttpStatus status, String message, String debugMessage, String constraint) {
this.status = status;
this.message = message;
this.debugMessage = debugMessage;
this.constraint = constraint;
}
在 React 应用程序上将创建一个包到这个约束:
DUPLICATED_RECORD
USED_RECORD