Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Spring Boot中捕获hibernate/jpa约束冲突?_Hibernate_Spring Mvc_Spring Boot_Spring Data Jpa - Fatal编程技术网

如何在Spring Boot中捕获hibernate/jpa约束冲突?

如何在Spring Boot中捕获hibernate/jpa约束冲突?,hibernate,spring-mvc,spring-boot,spring-data-jpa,Hibernate,Spring Mvc,Spring Boot,Spring Data Jpa,我无法在中捕获ConstraintViolationException(或DataIntegrityViolationException) ResponseEntityExceptionHandler。 我想在响应中返回jpa失败(例如,违反了哪个约束)。 (我不希望在方法参数和catch handleMethodArgumentNotValid上使用@Valid) 。。。 导入org.hibernate.exception.ConstraintViolationException; 导入org

我无法在中捕获ConstraintViolationException(或DataIntegrityViolationException) ResponseEntityExceptionHandler。 我想在响应中返回jpa失败(例如,违反了哪个约束)。 (我不希望在方法参数和catch handleMethodArgumentNotValid上使用@Valid)

。。。
导入org.hibernate.exception.ConstraintViolationException;
导入org.springframework.dao.DataIntegrityViolationException;
@控制器建议
公共类PstExceptionHandler扩展了ResponseEntityExceptionHandler{
@ExceptionHandler({ConstraintViolationException.class})
公共责任处理培训暴力(
ConstraintViolationException(例如,WebRequest请求){
...
返回新的ResponseEntity(…);
}
}
导入javax.persistence.*;
导入javax.validation.constraints.NotNull;
导入javax.validation.constraints.Size;
@实体
公立班学生{
@身份证
私人长id;
@NotNull
私有字符串名称;
@NotNull
@大小(最小值=7,message=“Passport应至少包含7个字符”)
私人字符串护照号码;
公立学生(){
}
...
}
@请求映射(value=“/addstudent”…)
@应答器
公共响应添加学生(@RequestBody StudentDto StudentDto){
学生=新生();
student.setId(studentDto.getId());//1L
student.setName(studentDto.getName());/“helen”
student.setPassportNumber(studentDto.getPassportNumber());/“321”
studentRepository.save(学生);
返回ResponseEntity.accepted().主体(学生);
}

谢谢…

像ConstraintViolationException这样的异常不被考虑在内,因为它们是从HibernateException扩展而来的。您可以查看一下,这些异常都包装在Hibernate异常中

@ExceptionHandler({TransactionSystemException.class})
public ResponseEntity<Object> handleConstraintViolation(TransactionSystemException ex, WebRequest request) {

    if (ex.getCause() instanceof RollbackException) {
       RollbackException rollbackException = (RollbackException) ex.getCause();
         if (rollbackException.getCause() instanceof ConstraintViolationException) {
             return new ResponseEntity<Object>(...);
         }
    ...
    }
    ...

    return new ResponseEntity<Object>(...);
}
@ExceptionHandler({TransactionSystemException.class})
公共响应handleConstraintViolation(TransactionSystemException除外,WebRequest请求){
如果(例如getCause()实例RollbackException){
RollbackException RollbackException=(RollbackException)ex.getCause();
if(rollbackException.getCause()instanceof ConstraintViolationException){
返回新的ResponseEntity(…);
}
...
}
...
返回新的ResponseEntity(…);
}
有三种方法:

  • @Valid
    \
    @Validated
    注释

    一旦在参数级别使用了它们,就可以通过方法注入
    错误
    \
    BindingResult
    类型实现使用冲突

  • 每次将处于无效状态的实体传递给
    .save()
    .persist()
    休眠方法时,都会引发
    ConstraintViolationException

  • 实体可以通过注入的
    LocalValidatoryFactoryBean.validate()
    方法进行手动验证。然后,通过传递
    错误
    对象的实现,可以获得约束冲突。
    确切地说,如何在内部实现
    @Valid
    \
    @Validated
    注释


  • 您无法捕获ConstraintViolationException.class,因为它没有传播到代码的该层,而是由较低的层捕获,并在另一个类型下包装和重新发布。因此,命中web层的异常不是ConstraintViolationException。所以你可以这样做:

    @ExceptionHandler({TransactionSystemException.class})
    protected ResponseEntity<Object> handlePersistenceException(final Exception ex, final WebRequest request) {
        logger.info(ex.getClass().getName());
        //
        Throwable cause = ((TransactionSystemException) ex).getRootCause();
        if (cause instanceof ConstraintViolationException) {        
    
            ConstraintViolationException consEx= (ConstraintViolationException) cause;
            final List<String> errors = new ArrayList<String>();
            for (final ConstraintViolation<?> violation : consEx.getConstraintViolations()) {
                errors.add(violation.getPropertyPath() + ": " + violation.getMessage());
            }
    
            final ApiError apiError = new ApiError(HttpStatus.BAD_REQUEST, consEx.getLocalizedMessage(), errors);
            return new ResponseEntity<Object>(apiError, new HttpHeaders(), apiError.getStatus());
        }
        final ApiError apiError = new ApiError(HttpStatus.INTERNAL_SERVER_ERROR, ex.getLocalizedMessage(), "error occurred");
        return new ResponseEntity<Object>(apiError, new HttpHeaders(), apiError.getStatus());
    }
    
    @ExceptionHandler({TransactionSystemException.class})
    受保护的响应handlePersistenceException(最终异常,例如,最终WebRequest请求){
    logger.info(例如getClass().getName());
    //
    可丢弃原因=((TransactionSystemException)ex).getRootCause();
    如果(导致ConstraintViolationException的实例){
    ConstraintViolationException consEx=(ConstraintViolationException)原因;
    最终列表错误=新建ArrayList();
    for(最终约束冲突:consEx.getConstraintViolations()){
    添加(违例。getPropertyPath()+“:“+违例。getMessage());
    }
    final APIRROR APIRROR=新的APIRROR(HttpStatus.BAD_请求,consEx.getLocalizedMessage(),errors);
    返回新的ResponseEntity(APIRROR,new-HttpHeaders(),APIRROR.getStatus());
    }
    final APIRROR APIRROR=新的APIRROR(HttpStatus.INTERNAL_SERVER_ERROR,例如getLocalizedMessage(),“发生错误”);
    返回新的ResponseEntity(APIRROR,new-HttpHeaders(),APIRROR.getStatus());
    }
    
    我遇到了同样的问题,因此我必须捕获
    jdbception
    异常:

    @ExceptionHandler({JDBCException.class})
    public ResponseEntity<Object> handleConstraintViolation(TransactionSystemException ex, WebRequest request) {
    
        if (ex.getCause() instanceof ConstraintViolationException) {
            ...
        }   
    
        return new ResponseEntity<Object>(...);
    }
    
    @ExceptionHandler({jdbception.class})
    公共响应handleConstraintViolation(TransactionSystemException除外,WebRequest请求){
    if(例如getCause()instanceof ConstraintViolationException){
    ...
    }   
    返回新的ResponseEntity(…);
    }
    
    像这样的东西会有帮助:

    @ExceptionHandler(value = {DataIntegrityViolationException.class})
    public ResponseEntity<String> handlePreconditionFailed(DataIntegrityViolationException exception) {
            LOG.error(ERROR_MESSAGE, exception);
            return ResponseEntity.status(HttpStatus.CONFLICT).build();
    }
    
    @ExceptionHandler(值={DataIntegrityViolationException.class})
    公共响应句柄修复失败(DataIntegrityViolationException异常){
    日志错误(错误消息,异常);
    返回ResponseEntity.status(HttpStatus.CONFLICT.build();
    }
    
    您能试试HibernateException吗?只需更新这个@ExceptionHandler({HibernateeException.class}),并让我知道您的答案是什么..?谢谢-尽管它并没有解决问题。问题依然存在。哦,对了,我已经看了一下,像ConstraintViolationException这样的异常并没有被考虑在内,因为正如我所想,它们是从HIbernateException扩展而来的。因此,将引发PersistenceException,而不是从HibernateeException扩展的任何异常。所以我认为您应该更新如下内容:@ExceptionHandler({PersistenceException.class})public ResponseEntity handleConstraintViolation(PersistenceException ex,WebRequest request){if(ex instanceof ConstraintViolationException){ConstraintViolationException consEx=
    @ExceptionHandler(value = {DataIntegrityViolationException.class})
    public ResponseEntity<String> handlePreconditionFailed(DataIntegrityViolationException exception) {
            LOG.error(ERROR_MESSAGE, exception);
            return ResponseEntity.status(HttpStatus.CONFLICT).build();
    }