2013-03-06 56 views
0

我使用hibernate与spring来创建一个宁静的服务应用程序。我想在操作失败时返回错误消息。例如,如果在检测到重复的主键时创建帐户,我想设置用户名不可用的消息。如何知道哪个实体导致SQL异常

try 
{ 
    Account account = accountDao.createAccount(accName, emailAdd); 
    result.accountId = account.getIdAccount(); 
} 
catch (DataAccessException e) 
{ 
    result.errorMessage = "something like this account name is already taken"; <***** 
    Throwable th = e.getCause(); 
    if(th!=null && th instanceof ConstraintViolationException) 
    { 
     ConstraintViolationException cve = (ConstraintViolationException) th; 
     log.debug("Error code = " + cve.getErrorCode() + " ConstraintName = " + cve.getConstraintName()); 
    } 
} 
catch (Exception e) 
{ 
    result.errorMessage = "failed to create account"; 
} 

因此,使用stacktace我可以看到,内部异常是

Caused by: org.hibernate.exception.ConstraintViolationException: Duplicate entry 'my account name' for key 'name_account' 

,但是当我试图让cve.getConstraintName(),则返回null。 (cve.getConstraintName()是1062)

有没有什么方法可以获得我要找的磨料?

供参考,这是完整的堆栈跟踪:

org.springframework.dao.DataIntegrityViolationException: Duplicate entry 'name Name' for key 'name_account'; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: Duplicate entry 'name Name' for key 'name_account' 
    at org.springframework.orm.hibernate4.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:138) 
    at org.springframework.orm.hibernate4.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:594) 
    at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:476) 
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:755) 
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:724) 
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:387) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) 
    at com.sun.proxy.$Proxy384.createAccount(Unknown Source) 
    at com.gears42.econ.domain.business.AccountService.createAccountWithDefaultPlan(AccountService.java:36) 
    at com.gears42.econ.domain.controller.SuperuserController.createAccount(SuperuserController.java:33) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:219) 
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:132) 
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) 
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:745) 
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:686) 
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80) 
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925) 
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856) 
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:920) 
    at org.springframework.web.servlet.FrameworkServlet.doPut(FrameworkServlet.java:838) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:650) 
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:801) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330) 
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118) 
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) 
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342) 
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192) 
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160) 
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346) 
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259) 
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) 
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) 
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) 
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99) 
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936) 
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407) 
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004) 
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589) 
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) 
    at java.lang.Thread.run(Unknown Source) 
Caused by: org.hibernate.exception.ConstraintViolationException: Duplicate entry 'name Name' for key 'name_account' 
    at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:74) 
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49) 
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125) 
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110) 
    at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:129) 
    at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81) 
    at com.sun.proxy.$Proxy394.executeUpdate(Unknown Source) 
    at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:56) 
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3028) 
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3469) 
    at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:88) 
    at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:362) 
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:354) 
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:275) 
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326) 
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52) 
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1213) 
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:402) 
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101) 
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175) 
    at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:468) 
    ... 68 more 
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry 'name Name' for key 'name_account' 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source) 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source) 
    at java.lang.reflect.Constructor.newInstance(Unknown Source) 
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411) 
    at com.mysql.jdbc.Util.getInstance(Util.java:386) 
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1040) 
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4096) 
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4028) 
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2490) 
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2651) 
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2734) 
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155) 
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2458) 
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2375) 
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2359) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:122) 
    ... 84 more 

回答

1

试图抓住的org.springframework.dao。 DataIntegrityViolationException代替DataAccessException的

抛出该异常当试图插入或更新数据的结果 违反完整性约束。请注意,这不是纯粹的关系概念;大多数数据库 类型都需要唯一主键。

+0

我已经试过了。它没有帮助。 – 2013-03-06 12:19:24

+0

如果您将它转换为ConstraintViolationException(如上例所示),则应该直接从DataIntegrityViolationException中获取消息 – 2013-03-06 12:21:14

+0

我不想要消息。我想要约束失败的列名。在我的情况下,它是“name_account”。 ConstraintViolationException.getConstraintName()应该返回这个列名,但它返回null。 – 2013-03-06 12:24:01

2

检查ConstraintViolationExceptiongetConstraintName()来检查哪个DB约束被违反。在那里你可以找到哪个实体给出了问题。 以下是我用过的示例代码。

} catch (ConstraintViolationException conEx) { 
      if (conEx.getConstraintName().contains("PROJECT_UK")) { 
       //TODO Project Entity is violating it's constrain 
      } else if (conEx.getConstraintName().contains(
        "PROJECT_BATCH_CLASS_FK")) { 
       //TODO BatchClass entity within Project is giving issue 
      } else if (conEx.getConstraintName().contains("OPPRTNTY__UN")) { 
       //TODO Project Entitiy is giving the issue 
      } else { 
       //TODO Unknown entity/constrain is causing the issue 
      } 
      LOGGER.ERROR("My log message", conEx); 

我用contains,因为我想让这个应用程序运行在多个DB架构上。默认情况下getConstraintName带有DB名称就像

MyDBName.ConstrainName