2012-01-19 11 views
7

Mam problemy z obsługą wyjątków DataAccessException.Wyrzucony wiosenny wyjątek JpaSystemException zamiast DuplicateKeyException

Po naruszeniu ograniczenia klucza uniksowego otrzymałem wyjątek JpaSystemException, a nie wyjątek DuplicateKeyException!

Znalazłem wątek mówiący o tym problemie, ale nikt mi nie pomoże rozwiązać tego problemu. Jak mogę mapować do konkretnego wyjątku org.springframework.dao?

Mój plik persistence.xml wyglądać następująco:

<?xml version="1.0" encoding="UTF-8" standalone="no"?> 
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> 
    <persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL"> 
     <provider>org.hibernate.ejb.HibernatePersistence</provider>   
     <class>...</class> 
     <class>...</class> 
     ... 
     <exclude-unlisted-classes /> 
     <properties> 
      <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/> 
      <property name="hibernate.hbm2ddl.auto" value="update"/> 
      <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/> 
      <property name="hibernate.connection.charSet" value="UTF-8"/> 
      <property name="hibernate.show.sql" value="true"/> 

      <property name="hibernate.ejb.event.post-insert" value="org.hibernate.ejb.event.EJB3PostInsertEventListener,org.hibernate.envers.event.AuditEventListener" /> 
     <property name="hibernate.ejb.event.post-update" value="org.hibernate.ejb.event.EJB3PostUpdateEventListener,org.hibernate.envers.event.AuditEventListener" /> 
     <property name="hibernate.ejb.event.post-delete" value="org.hibernate.ejb.event.EJB3PostDeleteEventListener,org.hibernate.envers.event.AuditEventListener" /> 
     <property name="hibernate.ejb.event.pre-collection-update" value="org.hibernate.envers.event.AuditEventListener" /> 
      <property name="hibernate.ejb.event.pre-collection-remove" value="org.hibernate.envers.event.AuditEventListener" /> 
     <property name="hibernate.ejb.event.post-collection-recreate" value="org.hibernate.envers.event.AuditEventListener" /> 
    </properties>   
    </persistence-unit>  
    <persistence-unit name="persistenceUnitI24" transaction-type="RESOURCE_LOCAL"> 
     <provider>org.hibernate.ejb.HibernatePersistence</provider> 
     <class>...</class> 
     <class>...</class> 
     <exclude-unlisted-classes /> 
     <properties> 
      <property name="hibernate.dialect" value="org.hibernate.dialect.SQLServerDialect"/> 
      <property name="hibernate.hbm2ddl.auto" value="validate"/> 
      <property name="hibernate.connection.charSet" value="UTF-8"/> 
      <property name="hibernate.showsql" value="true"/>   
     </properties> 
    </persistence-unit> 
</persistence> 

I konfiguracje o menedżera transakcji MySQL:

<bean id="entityManagerFactory" 
      class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" 
      p:dataSource-ref="dataSource" 
      p:persistenceUnitName="persistenceUnit" 
      p:jpaProperties=""> 
      <property name="jpaVendorAdapter"> 
     <bean 
      class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> 
       <property name="showSql" value="true" /> 
       <property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect" /> 
       <property name="database" value="MYSQL"/>   
     </bean> 
     </property> 
      <property name="jpaDialect"> 
     <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" /> 
      </property> 
    </bean> 

    <bean id="transactionManager" 
      class="org.springframework.orm.jpa.JpaTransactionManager" 
      p:entityManagerFactory-ref="entityManagerFactory"/> 

    <tx:annotation-driven transaction-manager="transactionManager" /> 

mam pominięto konfigurację o sqlserver bo myślę, że nie jest istotne, . Nie interesuje mnie błąd tłumaczenia dotyczący tego db.

Mam także fasoli:

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

Próbując zrobić następujący prosty test junit:

@Test(expected=DuplicateKeyException.class) 
public void createNewUbi(){ 
    Ubi ubi = new Ubi(); 
    ubi.setCode("A"); 
    ubiDao.save(ubi);  

    ubi = new Ubi(); 
    ubi.setCode("A"); 

    ubiDao.save(ubi);     
} 

dostałam od mojego dziennika:

ERROR: org.hibernate.util.JDBCExceptionReporter - Duplicate entry 'A' for key 'code' 

Catching z wyjątkiem drugiego zapisania połączenia zauważyłem, że mam:

JpaSystemException: cause: javax.persistence.PersistenceException 
PersistenceException: cause: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException 

Gdy próbuję zrobić wstawkę z webapp Mam ten wyjątek:

org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:311) 
    org.springframework.orm.jpa.aspectj.JpaExceptionTranslatorAspect.ajc$afterThrowing$org_springframework_orm_jpa_aspectj_JpaExceptionTranslatorAspect$1$18a1ac9(JpaExceptionTranslatorAspect.aj:15) 
    it.cpmapave.pm.dao.jpa.GenericDaoJpa.save(GenericDaoJpa.java:29) 
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    java.lang.reflect.Method.invoke(Method.java:597) 
    org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309) 
    org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) 
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 
    org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155) 
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) 
    $Proxy56.save(Unknown Source) 
    it.cpmapave.pm.service.amministrazione.SettoreServiceImpl.saveSettore(SettoreServiceImpl.java:34) 
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    java.lang.reflect.Method.invoke(Method.java:597) 
    org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309) 
    org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) 
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 
    org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110) 
    org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) 
    $Proxy57.saveSettore(Unknown Source) 
    it.cpmapave.pm.controller.amministrazione.SettoreController.create(SettoreController.java:42) 
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    java.lang.reflect.Method.invoke(Method.java:597) 
    org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176) 
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:436) 
    org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:424) 
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790) 
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719) 
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:669) 
    org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:585) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:641) 
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722) 
    org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304) 
    org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
    org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:113) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) 
    org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) 
    org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:369) 
    org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109) 
    org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381) 
    org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381) 
    org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381) 
    org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381) 
    org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381) 
    org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:35) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381) 
    org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:177) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381) 
    org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:187) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381) 
    org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381) 
    org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79) 
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381) 
    org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:168) 
    org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237) 
    org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167) 
    org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) 
    org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
    org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) 
    org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) 
    org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
    org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88) 
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) 
    org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) 
    org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
    org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224) 
    org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175) 
    org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) 
    org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164) 
    org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100) 
    org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929) 
    org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) 
    com.springsource.insight.collection.tcserver.request.HttpRequestOperationCollectionValve.invoke(HttpRequestOperationCollectionValve.java:84) 
    org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:405) 
    org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:279) 
    org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:515) 
    org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:300) 
    java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) 
    java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) 
    java.lang.Thread.run(Thread.java:662) 

mam włączone rejestrowanie zapytań mysql i mam następujące zapytanie:

insert into ubi (code, version) values ('A', 0) 

Gdybym spróbuj wykonać zapytanie z konsoli mysql Dostałem: ERROR 1062 (23000): Duplicate entry 'A' for key 'code'

Wyszukiwanie w sql-error-codes.xml w pakiecie org.springframework.jdbc.supportspring-jdbc-3.0.6.RELEASE.jar i stwierdził, że dla mysql db kod błędu 1062 jest skonfigurowany w ten sposób:

<property name="duplicateKeyCodes"> 
    <value>1062</value> 
</property> 

Więc myślę, że istnieje jakiś wyjątek tłumaczenia problemem z powodu złej konfiguracji właściwości .. ale który?

Używam Wiosna 3.0.6.RELEASE i hibernacji 3.6.9.FINAL

Dziękuję za wszelkie odpowiedzi! Marco

+0

@skaffman Ok, to jest podklasą UncategorizedDataAccessException a potem DataAccessException. Czy wiesz, w jaki sposób mogę odwzorować wyjątek skategoryzowany, na przykład DuplicateKeyException w moim przypadku? Dziękuję Ci! – gipinani

+0

@skaffman Zaktualizowałem swój wpis, aby uzyskać więcej informacji. – gipinani

+0

Znalazłem, że kiedy maven kompiluje projekt otrzymuję to OSTRZEŻENIE: porady zdefiniowane w org.springframework.orm.jpa.aspectj.JpaExceptionTranslatorAspect nie został zastosowany Czy może to być przyczyną? :) – gipinani

Odpowiedz

3

Ten problem nie jest związany ze sprężyną ani ze sterownikiem bazy danych. Musiałem to przez jakiś czas rozwiązać. Zaskoczyło mnie, że słoik dodatku hibernacji-uprawnienia3, który pozwala używać Hibernate jako dostawcy JPA, ma w tym miejscu słabe tłumaczenie wyjątku.Metoda AbstractEntityManagerImpl.convert() jest odpowiedzialna za konwersję HibernateException s do JPA PersistenceException s, ale nie obsługuje w ogóle żadnego wyjątku "duplikatu klucza" lub "unikalnego ograniczenia". Nawet model latest code on Github prawdopodobnie nie naprawił tego. Jeśli spojrzeć na to, metoda convert() ma długi łańcuch znaków ifs, ale żaden z nich nie obejmuje tego szczególnego rodzaju wyjątku, więc przechodzi do dołu i zostaje przetłumaczony na ogólny PersistenceException. To dość denerwujące.

4

Upewnij się, że Twój EntityManager ma ustawiony na nim vendorAdapter. Umożliwi to dostawcy jpa dostarczenie zaawansowanych kodów błędów.

1

Miałem ten zestaw w mojej konfiguracji.

transactionManager.setJpaDialect(new HibernateJpaDialect()); 

I komentuje ją i nagle moja aplikacja zaczął dawać DuplicateKeyException

Powiązane problemy