2012-01-19 2 views
7

У меня проблемы с обработкой DataAccessException.Spring Thrown JpaSystemException вместо DuplicateKeyException

Когда нарушение уникального ключа нарушено, я получил исключение JpaSystemException, а не исключение DuplicateKeyException!

Я нашел какую-то тему, говорящую об этой проблеме, но никто не помогает мне решить проблему. Как я могу сопоставить конкретное исключение org.springframework.dao?

Мой persistence.xml файл выглядеть следующим образом:

<?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> 

И конфигурации о менеджере 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" /> 

Я пропущенной конфигурацию о SQLServer, потому что я думаю, что это не имеет значения , Меня не интересует ошибка перевода об этом db.

Я также включил боб:

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

Попытка сделать следующий простой тест 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);     
} 

я получил от моего журнала:

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

Ловля исключение второго вызова сохранения я заметил, что у меня есть:

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

Если я пытаюсь сделать вставку из веб-приложение, я получил это исключение:

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) 

Я позволил MySQL протоколирование запросов, и я получил следующий запрос:

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

Если я попробуйте выполнить запрос из консоли mysql. Я получил: ERROR 1062 (23000): Duplicate entry 'A' for key 'code'

Поиск в sql-error-codes.xml в пакете org.springframework.jdbc.support из spring-jdbc-3.0.6.RELEASE.jar я обнаружил, что для БД MySQL код ошибки 1062 сконфигурирован таким образом:

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

Так что я думаю, что есть некоторая проблема Exception перевод из-за некорректной настройки свойств .. но?

Я использую Spring 3.0.6.RELEASE и гибернации 3.6.9.FINAL

Спасибо за любой ответ! Marco

+0

@skaffman Хорошо, это подкласс UncategorizedDataAccessException и затем DataAccessException. Вы знаете, как я могу сопоставить классификационное исключение, например DuplicateKeyException в моем случае? Спасибо! – gipinani

+0

@skaffman Я обновил свой пост с дополнительной информацией. – gipinani

+0

Я обнаружил, что, когда Maven компиляции проекта я получаю это ПРЕДУПРЕЖДЕНИЕ: совет определен в org.springframework.orm.jpa.aspectj.JpaExceptionTranslatorAspect не был применен Может ли это быть причиной? :) – gipinani

ответ

3

Эта проблема не связана с Spring или с вашим драйвером базы данных. Мне пришлось проработать это через некоторое время. Я с удивлением обнаружил, что hibernate-entitymanager jar, который позволяет использовать Hibernate в качестве поставщика JPA, имеет в нем плохой перевод исключений.Метод AbstractEntityManagerImpl.convert() отвечает за преобразование HibernateException s в JPA PersistenceException s, но он вообще не обрабатывает какие-либо исключения «дубликат ключа» или «уникальное ограничение». Даже latest code on Github, похоже, не исправил его. Если вы посмотрите на это, метод convert() имеет длинную цепочку ifs, но ни один из них не покрывает этот особый вид исключения, поэтому он проваливается в нижнюю часть и преобразуется в общий PersistenceException. Это довольно раздражает.

4

Убедитесь, что на вашем EntityManager установлен на нем vendorAdapter. Это позволит провайдеру jpa предоставлять расширенные коды ошибок.

1

У меня был этот набор в моей конфигурации.

transactionManager.setJpaDialect(new HibernateJpaDialect()); 

Я заметил его, и вдруг мое приложение начал давать DuplicateKeyException

Смежные вопросы