Spring dao异常翻译在测试和生产中表现不同

时间:2011-05-09 18:04:04

标签: hibernate spring orm jpa exception-handling

我在我的应用程序中使用Spring异常转换来转换底层ORM框架(Hibernate)中的异常,并且我发现在我的测试和生产环境中,ConstraintViolationExceptions的翻译方式不同。

在我的常规单元测试中,我有以下内容......

    // provide a non-unique name for a department entity
    shouldFail(DataIntegrityViolationException, {

        Department d = new Department(name: 'HR')
        departmentDao.persist(d)
    })

这很好 - 由于底层的 org.hibernate.exception.ConstraintViolationException ,引发了预期的DataIntegrityViolationException。在我的groovy服务代码中,我有以下代码块,它们应该捕获相同的DataIntegrityViolationException ...

    try{
        departmentDao.persist(department)
    }
    // There may be a constraint violation if a department with the same name already exists
    catch(DataIntegrityViolationException e){...}

但是在运行时,Spring并没有转换异常,因此运行时Hibernate异常会在堆栈中向上传播。

在stacktrace中提到了org.springframework.orm.jpa.JpaSystemException,根据文档是“特定于JPA的UncategorizedDataAccessException的子类”,JPA系统错误与任何具体的org.springframework都不匹配。 dao例外。“ ...

  

org.hibernate.exception.ConstraintViolationException:无法插入:[com.myapp.Department];嵌套异常是javax.persistence.PersistenceException:org.hibernate.exception.ConstraintViolationException:无法插入:[com.myapp.Department]   org.springframework.orm.jpa.JpaSystemException:org.hibernate.exception.ConstraintViolationException:无法插入:[com.myapp.Department];嵌套异常是javax.persistence.PersistenceException:org.hibernate.exception.ConstraintViolationException:无法插入:[com.myapp.Department]

我能看到的唯一可辨识的差异是我的测试由HSQLDB支持,而生产代码由MsSql数据库支持。任何人都可以解释为什么我的测试和运行时环境中的异常转换是不同的?

干杯。

编辑:

好的,还有一些细节......

我的测试应用程序上下文和生产应用程序上下文都定义了PersistenceExceptionTranslationPostProcessor,如下所示

<bean
    class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

就数据源而言,测试上下文使用HSQLDB数据源,该数据源在应用程序上下文中配置如下

<!-- HSQL-DB memory database; for testing only -->
<bean id="hsqlDs"
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="org.hsqldb.jdbcDriver" />
    <property name="url" value="jdbc:hsqldb:file:target/db/store;shutdown=true" />
    <property name="username" value="sa" />
    <property name="password" value="" />
</bean>

<bean id="persistenceUnitManager"
    class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
    <property name="persistenceXmlLocation" value="classpath:persistence-test.xml" />
    <property name="defaultDataSource" ref="hsqlDs" />
</bean>

<bean id="hsqlEntityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="store" />
    <property name="persistenceUnitManager" ref="persistenceUnitManager" />
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="showSql" value="true" />
            <property name="generateDdl" value="true" />
            <property name="databasePlatform" value="org.hibernate.dialect.HSQLDialect" />
        </bean>
    </property>
</bean>

prod上下文相当简单,因为它使用Glassfish中定义的JNDI数据源和persistence.xml中定义的持久性单元

<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" />

虽然如果我配置prod上下文以使用LocalEntityManagerFactoryBean,我会得到相同的结果。

似乎正在调用EntityManagerFactoryUtils来转换异常,但异常在两个环境中的转换方式不同。测试环境将异常转换为 org.springframework.dao.DataIntegrityViolationException ,但生产环境将其转换为 org.springframework.orm.jpa.JpaSystemException - 请参阅生产下面的堆栈跟踪:

org.springframework.orm.jpa.JpaSystemException: org.hibernate.exception.ConstraintViolationException: could not insert: [com.myapp.Department]; nested exception is javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not insert: [com.myapp.Department]
at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:311)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:369)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:58)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:163)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy233.persist(Unknown Source)

0 个答案:

没有答案