【问题标题】:ConstraintViolationException in spring rest春季休息中的 ConstraintViolationException
【发布时间】:2015-08-17 13:46:54
【问题描述】:

我有下一个 spring rest 控制器来处理我的异常:

@ExceptionHandler(ConstraintViolationException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public @ResponseBody
ExceptionResponseDTO hiberAnnotationExceptionHandler(ConstraintViolationException exception) {
    return  new ExceptionResponseDTO("Entity is null or we are out of range!", exception.getMessage(), ExceptionMapper.INSTANCE.exceptionToExceptionDTO(exception));
}

我的实体类:

@Entity
public class Device {

    @Id
    @Column(name="name", nullable = false)
    private String Name;

    @Column(name = "send_date")
    @NotNull
    private Date sendDate;
}

我尝试模拟 ConstraintViolationException,所以在我的控制器中我使用下一个代码:

Device d = new Device();
d.setName("sdsdsd");
d.setSendDate(null);
deviceRepository.save(d);

结果我收到下一个异常:

[dispatcherServlet]:? - Servlet.service() 用于 servlet [dispatcherServlet] 在带有路径 [] 的上下文中抛出异常 [Request 处理失败;嵌套异常是 org.springframework.transaction.TransactionSystemException:不能 提交 JPA 事务;嵌套异常是 javax.persistence.RollbackException:提交时出错 交易]有根本原因 javax.validation.ConstraintViolationException:验证失败 类 [com.entity.Device] 在组更新期间 [javax.validation.groups.Default, ] 列表 违反约束:[ ConstraintViolationImpl{interpolatedMessage='不能为空', propertyPath=sendDate, rootBeanClass=class com.entity.Device, messageTemplate='{javax.validation.constraints.NotNull.message}'} ]

从堆栈跟踪中可以看出,我首先收到 TransactionSystemException,因此我的 ExceptionHandler 方法 (hiberAnnotationExceptionHandler) 不会调用。所以我的问题是如何模拟这个异常(ConstraintViolationException)? 提前致谢。

【问题讨论】:

    标签: spring hibernate


    【解决方案1】:

    尝试重现后续步骤:

    • 添加到您的 WebConfiguration 文件
    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {
        return new MethodValidationPostProcessor();
    }
    
    • @Validated标记您的控制器

    • 在Controller的方法中用

    • 标记你的参数

    @Pattern(regexp = "\\d+") @RequestParam String param

    • 然后只需使用“一些没有数字的字符串”之类的参数调用该方法。


    如果您想使用该实体。做类似的事情

    @Valid @RequestBody Device device 
    

    在你的方法中。 您可以跳过之前的所有步骤。

    【讨论】:

      【解决方案2】:

      TransactionSystemException 的原因

      1. 休眠实体管理器负责抛出所有休眠异常

      如果你进入代码AbstractEntityManagerImpl.convert() 方法, 您会看到默认情况下它不处理任何特定异常,例如 ConstraintViolation,而是抛出并包装在 PersistenceException 中。

      1. 如果你在@Transaction内部调用你的代码并转换为TransactionSystemException,JPA事务管理器会捕获上述异常,你可以看到spring JPA事务管理器的代码class="org.springframework.orm.jpa.JpaTransactionManager"

      正确解决异常的解决方案

      1. 首先注册一个 JPA 方言,它可以拦截那些 HibernateExceptions 并在事务管理器 bean 中像这样包装到特定的 spring 异常中。
       <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
          <property name="entityManagerFactory" ref="entityManagerFactory"/>
          <property name="jpaDialect" ref="jpaDialect"/>
      </bean>
      
      <bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
      

      HibernateJpaDialect 捕获这些异常并转换为像这样的 Spring 特定异常

      if (ex instanceof ConstraintViolationException) {
                ConstraintViolationException jdbcEx = (ConstraintViolationException) ex;
                return new DataIntegrityViolationException(ex.getMessage()  + "; SQL [" + jdbcEx.getSQL() +
                        "]; constraint [" + jdbcEx.getConstraintName() + "]", ex);
            }
      
      1. 您还可以注册您的 entitymanager 正在使用 hibernate jpaVendorAdapter 以完成您在任何地方都使用 hibernate。
      <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
            <property name="packagesToScan" value="com.pack.model" />
              <property name="persistenceUnitManager" ref="persistenceUnitManager"/>
              <property name="persistenceUnitName" value="entityManager"/>
              <property name="jpaVendorAdapter" ref="jpaVendorAdapter"/>
          </bean>    <bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
      
      1. 现在在您的控制器中,您可以预期 dataIntegrityException 来自休眠方言,由于 ConstraintViolationException 而引发

      @ExceptionHandler(DataIntegrityViolationException.class)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-03-23
        • 2015-03-15
        • 1970-01-01
        • 1970-01-01
        • 2016-01-30
        • 2013-12-13
        • 1970-01-01
        相关资源
        最近更新 更多