我在处理 DataAccessException 时遇到了麻烦。

当违反唯一键约束时,我得到了 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 的配置,因为我认为这无关紧要。我对这个数据库的翻译错误不感兴趣。

我还包括了 bean :
<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  

如果我尝试从 webapp 进行插入,则会出现此异常:
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.supportspring-jdbc-3.0.6.RELEASE.jar我发现对于 mysql db,错误代码 1062 是这样配置的:
<property name="duplicateKeyCodes"> 
    <value>1062</value> 
</property> 

所以我认为由于配置错误的属性存在一些异常翻译问题..但是哪个?

我正在使用 Spring 3.0.6.RELEASE 和 Hibernate 3.6.9.FINAL

感谢您的任何回复!
马可

请您参考如下方法:

确保您的 EntityManager有一个 vendorAdapter设置它。这将允许您的 jpa 提供商提供高级错误代码。


评论关闭
IT干货网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!