Spring exception broadcasting mechanism not kicking

I have a scenario where I am deliberately trying to break unique constraint

while waiting for Spring DataIntegrityViolationException

, but that never happens. javax.persistence.PersistenceException

thrown out with reason org.hibernate.exception.ConstraintViolationException

, but no Spring translation.

Classes DAO

and are Service

annotated correctly with the @Repository

and @Service

and @PersistenceContext

ed repository .

Services:

  @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;
  }
}

      

My config:

<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" />

      

Exception trace:

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

      

+3


source to share


2 answers


Probably the problem is that you don't have any PersistenceExceptionTranslator beans in your context that can unpack Hibernate JPA Persistence exceptions to find out what the reason is.

Try adding HibernateJpaDialect bean to your application context:

In Java

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

      



Or in XML

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

      

Hibernate AbstractEntityManagerImpl transfers Hibernate exceptions to JPA exceptions before Spring translates it. HibernateJpaDialect implements the Spring PersistenceExceptionTranslator interface and knows how to deploy these PersistenceExceptions.

+3


source


As I said, I had the same problem a couple of days ago. At least in my situation / confguration I solved the problem by using / implementing the PersistenceExceptionTranslationPostProcesor bean .

It can be contextualized in such a way

XML

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

      



JAVA

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

      

Even though the documentation states the following, I have not been able to confirm that LocalSessionFactoryBean

for Hibernate4

also implements this bean out of the box (I'm guessing it's a matter of diving into the code).

All Spring applicable resource factories (like LocalContainerEntityManagerFactoryBean) implement the PersistenceExceptionTranslator interface out of the box. As a consequence, all that is usually needed to enable automatic exclusion, the translation marks all affected beans (such as repositories or DAOs) with the @Repository annotation, along with defining this post processor as a bean in the application context.

+2


source







All Articles