ConstraintViolationException

ConstraintViolationException

我在Entity类中定义了一种用于验证电子邮件的模式。在验证异常处理程序类中,我为ConstraintViolationException添加了处理程序。我的应用程序使用SpringBoot 1.4.5。

Profile.java

@Entity
@EntityListeners(AuditingEntityListener.class)
@Table(name = "profile")
public class Profile extends AuditableEntity {

  private static final long serialVersionUID = 8744243251433626827L;

  @Column(name = "email", nullable = true, length = 250)
  @NotNull
  @Pattern(regexp = "^([^ @])+@([^ \\.@]+\\.)+([^ \\.@])+$")
  @Size(max = 250)
  private String email;
....
}

ValidationExceptionHandler.java
@ControllerAdvice
public class ValidationExceptionHandler extends ResponseEntityExceptionHandler {

  private MessageSource messageSource;

  @Autowired
  public ValidationExceptionHandler(MessageSource messageSource) {
    this.messageSource = messageSource;
  }

  @ExceptionHandler(ConstraintViolationException.class)
  public ResponseEntity<Object> handleConstraintViolation(ConstraintViolationException ex,
  WebRequest request) {
    List<String> errors = new ArrayList<String>();
    ....
    }
}

当我运行代码并传递无效的电子邮件地址时,出现以下异常。 handleConstraintViolation中的代码永远不会执行。异常中返回的http状态是500,但是我想返回400。我知道如何实现这一点吗?
2017-07-12 22:15:07.078 ERROR 55627 --- [nio-9000-exec-2] o.h.c.s.u.c.UserProfileController        : Validation failed for classes [org.xxxx.common.service.user.domain.Profile] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
ConstraintViolationImpl{interpolatedMessage='must match "^([^ @])+@([^ \.@]+\.)+([^ \.@])+$"', propertyPath=email, rootBeanClass=class org.xxxx.common.service.user.domain.Profile, messageTemplate='{javax.validation.constraints.Pattern.message}'}]

javax.validation.ConstraintViolationException: Validation failed for classes [org.xxxx.common.service.user.domain.Profile] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
ConstraintViolationImpl{interpolatedMessage='must match "^([^ @])+@([^ \.@]+\.)+([^ \.@])+$"', propertyPath=email, rootBeanClass=class org.xxxx.common.service.user.domain.Profile, messageTemplate='{javax.validation.constraints.Pattern.message}'}]

at  org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:138)

at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreInsert(BeanValidationEventListener.java:78)

最佳答案

您无法捕获ConstraintViolationException.class,因为它没有传播到代码的那一层,它被较低的层捕获,并包装并重新抛出为另一种类型。因此,到达您的Web层的异常不是ConstraintViolationException

就我而言,这是TransactionSystemException
我正在使用Spring的@TransactionalJpaTransactionManager批注。当事务中出现问题时,EntityManager会引发回滚异常,该异常会由TransactionSystemException转换为JpaTransactionManager

因此,您可以执行以下操作:

@ExceptionHandler({ TransactionSystemException.class })
public ResponseEntity<RestResponseErrorMessage> handleConstraintViolation(Exception ex, WebRequest request) {
    Throwable cause = ((TransactionSystemException) ex).getRootCause();
    if (cause instanceof ConstraintViolationException) {
        Set<ConstraintViolation<?>> constraintViolations = ((ConstraintViolationException) cause).getConstraintViolations();
        // do something here
    }
}

10-08 03:29