春假

时间:2015-08-17 13:46:55

标签: spring hibernate

我有下一个春季休息控制器来处理我的异常:

@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的Servlet.service()   路径[]的上下文中的[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 )? 提前谢谢。

2 个答案:

答案 0 :(得分:3)

TransactionSystemException的原因

  1. Hibernate实体管理器负责抛出所有hibernate异常
  2. 如果你进入代码AbstractEntityManagerImpl.convert()方法, 您将看到默认情况下它不处理任何特定的异常,如ConstraintViolation,而只是抛出并包装在PersistenceException中。

    1. 如果您在@Transaction中调用代码并转换为TransactionSystemException,JPA事务管理器会捕获上述异常,您可以看到spring JPA事务管理器类的代码=" org.springframework.orm.jpa.JpaTransactionManager&# 34;
    2. 正确解决异常的解决方案

      1. 首先注册一个JPA方言,它可以拦截那些HibernateExceptions并在事务管理器bean中包装成这样的特定spring异常。
      2.  <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捕获这些异常,并转换为像这样的弹簧特定异常

        if (ex instanceof ConstraintViolationException) {
                  ConstraintViolationException jdbcEx = (ConstraintViolationException) ex;
                  return new DataIntegrityViolationException(ex.getMessage()  + "; SQL [" + jdbcEx.getSQL() +
                          "]; constraint [" + jdbcEx.getConstraintName() + "]", ex);
              }
        
        1. 您还可以注册您的实体管理器正在使用hibernate jpaVendorAdapter来完成您在任何地方使用hibernate。
        2. <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. 现在在你的控制器中,你可以期待由于ConstraintViolationException而引发的hibernate方言的dataIntegrityException
          2.   

            @ExceptionHandler(DataIntegrityViolationException.class)

答案 1 :(得分:-2)

尝试重现下一步:

  • 添加到您的WebConfiguration文件
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
    return new MethodValidationPostProcessor();
}
  • 使用@Validated

  • 标记您的控制器
  • 使用

  • 在Controller方法中标记您的参数
  

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

  • 然后使用&#34;某些不带数字的字符串&#34;。
  • 等参数调用该方法


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

的事情
@Valid @RequestBody Device device 

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