Spring的异常翻译机制没有开始

时间:2015-01-06 18:50:15

标签: hibernate spring-mvc spring-orm

我有一个场景,我故意试图违反unique constraint,期望抛出Spring DataIntegrityViolationException,但事实并非如此。 javax.persistence.PersistenceException引发org.hibernate.exception.ConstraintViolationException,但没有弹出翻译。

DAOService类已正确注释@Repository@Service以及存储库@PersistenceContext

服务:

  @Service
  public class BookServiceImpl implements BookService {
  @Inject private BookDAO bookDao;

  @Transactional(propagation = Propagation.REQUIRED)
  public Book createBook(Book book) {
    Book bk = null;
    try {
      bk = bookDao.makePersistent(book);
    } catch (AppDAOException e) {
      throw new AppServiceException(e);
    }
    return bk;
  }
}

我的配置:

<bean id="libmsEMF"
    class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="libmsDS" />
    <property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="libmsEMF" />
    <property name="dataSource" ref="libmsDS" />
</bean>

<bean id="jpaVendorAdapter"
    class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">

    <property name="database" value="SQL_SERVER" />
    <property name="showSql" value="false" />
    <property name="generateDdl" value="false" />
    <property name="databasePlatform" value="org.hibernate.dialect.SQLServer2008Dialect" />
</bean>

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

异常追踪:

Caused by: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement
  at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1763)
  at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1677)
  at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1683)
  at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1187)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:606)
  at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:289)
  at com.sun.proxy.$Proxy60.persist(Unknown Source)
  at com.hurontg.common.persistence.AbstractGenericDAOImpl.makePersistent(AbstractGenericDAOImpl.java:103)
  ... 57 more
Caused by: org.hibernate.exception.ConstraintViolationException: could not execute statement
  at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:129)
  at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
  at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126)
  at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112)
  at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:211)
  at org.hibernate.id.IdentityGenerator$GetGeneratedKeysDelegate.executeAndExtract(IdentityGenerator.java:96)
  at org.hibernate.id.insert.AbstractReturningDelegate.performInsert(AbstractReturningDelegate.java:58)
  at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3032)
  at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3558)
  at org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:98)
  at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:490)
  at org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:195)
  at org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:179)
  at org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:214)
  at org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:324)
  at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:288)
  at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:194)
  at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:125)
  at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:84)
  at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:206)
  at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:149)
  at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:75)
  at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:811)
  at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:784)
  at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:789)
  at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1181)
  ... 64 more
Caused by: java.sql.SQLException: Violation of UNIQUE KEY constraint 'UK_AUTHOR_TITLE'. Cannot insert duplicate key in object 'dbo.BOOK'. The duplicate key value is (Jim Corbett, The Temple Tiger).
  at net.sourceforge.jtds.jdbc.SQLDiagnostic.addDiagnostic(SQLDiagnostic.java:372)
  at net.sourceforge.jtds.jdbc.TdsCore.tdsErrorToken(TdsCore.java:2886)
  at net.sourceforge.jtds.jdbc.TdsCore.nextToken(TdsCore.java:2328)
  at net.sourceforge.jtds.jdbc.TdsCore.getMoreResults(TdsCore.java:638)
  at net.sourceforge.jtds.jdbc.JtdsStatement.processResults(JtdsStatement.java:614)
  at net.sourceforge.jtds.jdbc.JtdsStatement.executeSQL(JtdsStatement.java:573)
  at net.sourceforge.jtds.jdbc.JtdsPreparedStatement.executeUpdate(JtdsPreparedStatement.java:707)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:606)
  at org.apache.tomcat.jdbc.pool.interceptor.AbstractQueryReport$StatementProxy.invoke(AbstractQueryReport.java:235)
  at com.sun.proxy.$Proxy70.executeUpdate(Unknown Source)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:606)
  at org.apache.tomcat.jdbc.pool.interceptor.AbstractQueryReport$StatementProxy.invoke(AbstractQueryReport.java:235)
  at com.sun.proxy.$Proxy70.executeUpdate(Unknown Source)
  at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:208)
  ... 85 more

2 个答案:

答案 0 :(得分:3)

问题可能在于您在上下文中没有任何PersistenceExceptionTranslator bean,可以解开Hibernate的JPA Persistence异常以查看原因。

尝试将HibernateJpaDialect bean添加到应用程序上下文中:

在Java中

@Bean
public HibernateJpaDialect hibernateJpaDialect() {
    return new HibernateJpaDialect();
}

或XML格式

<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />

Hibernate的AbstractEntityManagerImpl在 Spring执行翻译之前将Hibernate的异常包装到JPA异常中。 HibernateJpaDialect实现了Spring的PersistenceExceptionTranslator接口,并知道如何解包这些PersistenceExceptions。

答案 1 :(得分:2)

正如我告诉你的那样,我几天前遇到了同样的问题。至少在我的情况/配置中,我通过使用/实现bean PersistenceExceptionTranslationPostProcesor解决了这个问题。

它可以通过这种方式包含在上下文中,

<强> XML

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

<强> JAVA

@Bean 
public HibernateExceptionTranslator hibernateExceptionTranslator() { 
    return new HibernateExceptionTranslator(); 
}

虽然文档中说明了以下内容,但我无法确认LocalSessionFactoryBean Hibernate4是否也开箱即用(我想这是潜入代码的问题)。< / p>

  

所有Spring的适用资源工厂(例如   LocalContainerEntityManagerFactoryBean)实现   PersistenceExceptionTranslator接口开箱即用。作为一个   结果,启用自动异常通常需要的一切   翻译正在标记所有受影响的bean(例如存储库或   DAO)与@Repository注释,以及定义它   后处理器作为应用程序上下文中的bean。