如何在Spring Boot中捕获休眠/ jpa约束违规?

时间:2018-11-04 14:15:41

标签: hibernate spring-mvc spring-boot spring-data-jpa

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

...
import org.hibernate.exception.ConstraintViolationException;
import org.springframework.dao.DataIntegrityViolationException;

@ControllerAdvice
public class PstExceptionHandler extends ResponseEntityExceptionHandler {

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

        ...

        return new ResponseEntity<Object>(...);
    }
}

import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

@Entity
public class Student {

    @Id
    private Long id;

    @NotNull
    private String name;

    @NotNull
    @Size(min=7, message="Passport should have at least 7 characters")
    private String passportNumber;

    public Student() {
    }

...

}

@RequestMapping(value = "/addstudent"...)
@ResponseBody
public ResponseEntity<Object> addStudent(@RequestBody StudentDto studentDto) {

    Student student = new Student();
    student.setId(studentDto.getId());                          // 1L
    student.setName(studentDto.getName());                      // "helen"
    student.setPassportNumber(studentDto.getPassportNumber());  // "321"

    studentRepository.save(student);

    return ResponseEntity.accepted().body(student);
}

谢谢...

5 个答案:

答案 0 :(得分:0)

诸如ConstraintViolationException之类的异常未考虑在内,因为它们是从HibernateException扩展而来的。您可以查看exceptions in convert method,它们被包装在Hibernate Exceptions中。

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

答案 1 :(得分:0)

有3种方法:

  1. @Valid \ @Validated注释。

    一旦在参数级别使用它们,就可以通过方法注入的Errors \ BindingResult类型的实现来实现违规。

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

  4. 实体可以通过注入的LocalValidatorFactoryBean.validate()方法手动验证。然后可以通过传递的Errors对象的实现来获得约束违规。 确切地说,@Valid \ @Validated注释是如何在内部实现的。

答案 2 :(得分:0)

您不能捕获ConstraintViolationException.class,因为它没有传播到代码的这一层,它被较低的层捕获,并包装并重新抛出为另一种类型。因此,到达您的Web层的异常不是ConstraintViolationException。因此,您可以执行以下操作:

for col in  range(len(df1.columns)):
    col_name = df1.iloc[:,col].name
    df1[col_name] = df1[col_name].apply(lambda x: x.replace("'", '"').replace('u"', '"') if type(x) == str else x)

答案 3 :(得分:0)

我遇到了同样的问题,因此不得不抓到java.util.ArrayList$Itr异常:

JDBCException

答案 4 :(得分:0)

这样的事情会有所帮助:

@ExceptionHandler(value = {DataIntegrityViolationException.class})
public ResponseEntity<String> handlePreconditionFailed(DataIntegrityViolationException exception) {
        LOG.error(ERROR_MESSAGE, exception);
        return ResponseEntity.status(HttpStatus.CONFLICT).build();
}