我们项目使用的是springMVC、Spring、Hibbernat的框架,我在做数据保存是遇到唯一索引冲突报异常,我试图在service层和Controller做异常的捕获,但是捕获不到异常,就直接在最外层报错了,所以我只能把事务加在最外层的Controller上面去才能事务回滚,但是我没办法捕获异常给接口返回准确的信息,请大神给指点下,谢谢了! 我的一段加异常捕获的代码: try { balanceSourceService.save(source); }catch (Exception e) { e.printStackTrace(); }
下面是我的代码最外层报的异常: 严重: Servlet.service() for servlet spring threw exception com.mysql.jdbc.exceptions.MySQLIntegrityConstraintViolationException: Duplicate entry ""1112-100-20798257826887681-2"" for key 2 at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:931) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2941) at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1623) at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1715) at com.mysql.jdbc.Connection.execSQL(Connection.java:3249) at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1268) at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1541) at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1455) at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1440) at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeUpdate(NewProxyPreparedStatement.java:105) at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:133) at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:58) at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3067) at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3509) at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:88) at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:377) at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:369) at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:286) at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:339) at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52) at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1234) at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:404) 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:554) 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:475) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:270) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631) at com.eastelsoft.framework.controller.BalanceController$$EnhancerByCGLIB$$d1188a37.PayFees(<generated>) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) 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:936) at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:838) at javax.servlet.http.HttpServlet.service(HttpServlet.java:637) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812) at javax.servlet.http.HttpServlet.service(HttpServlet.java:717) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at com.eastelsoft.framework.manager.AuthenticationFilter.doFilter(AuthenticationFilter.java:35) 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:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.shiro.web.servlet.AbstractShiroFilter.executeChain(AbstractShiroFilter.java:449) at org.apache.shiro.web.servlet.AbstractShiroFilter$1.call(AbstractShiroFilter.java:365) at org.apache.shiro.subject.support.SubjectCallable.doCall(SubjectCallable.java:90) at org.apache.shiro.subject.support.SubjectCallable.call(SubjectCallable.java:83) at org.apache.shiro.subject.support.DelegatingSubject.execute(DelegatingSubject.java:383) at org.apache.shiro.web.servlet.AbstractShiroFilter.doFilterInternal(AbstractShiroFilter.java:362) at org.apache.shiro.web.servlet.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:125) 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:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454) at java.lang.Thread.run(Thread.java:619) |
|
上面的那段代码 是我为了 在最底层捕获异常加的, 那个save是我封装了下 Hibernate的save方法,没有做任何处理的,同样捕获不到
|
|
1112-100-20798257826887681-2 用这个去你的表里查一下,看有没有2个
|
|
你确定没进catch吗 |
|
什么是最外层报错,异常捕获友好处理返回了么,异常打印在后台是可以的,出现在页面说明没处理
|
|
这是一种方法,先查在做处理,但是这个查和插入也会有那个极端的情况 在查的同时做了个插入的操作导致 索引冲突的异常吧 |
|
|
|
没看懂你的意思。 先查——判断——插入不是正常的么? |
|
是的,一般的话 这个业务顺序是正常的,那为什么我在service的异常捕获不到,反而在我service的外层Controller层可以捕获到,这个不明白为什么 |
|
你try catch写到service中怎么可能补货不到,你service的代码里面又try catch吗
|
|
没有的,在我service调用的那个save方法就是封装的hibernate的了,不知道为啥 在service层捕获不到,但是在service的外层也就是action层可以捕获到。 请您看下:http://bbs.csdn.net/topics/390050093?page=1#post-398522654 |
|
10分 |
按你所描述的,应该是在service层事物没有提交,所以,延迟到COntrol层才报错,你检查下你事物配置。你可以手动提交先验证下,再做修改;
|
你service里面没有try catch当然捕获不到了,你都是直接调用方法下去的,异常又没在service里面捕获,都是直接往上层抛出去的如果你在你的service.save方法里面做try catch肯定能捕获到的
|
|
其实我的这个方法就是在service层做的,只不过是调用了balanceSourceService里面的方法 try { balanceSourceService.save(source); }catch(DataAccessException e){ System.out.println("service================================="); e.printStackTrace(); } 不过他执行到这里 就会直接逃过去,到上面的controller才报出异常 ,就行这里面说的 http://bbs.csdn.net/topics/390050093?page=1#post-398522654 |
|
你只是捕获DataAccessException类型的异常,他抛的不是这种的异常你当然捕获不到了,你改成catch(Exception e) |
|
我使用注解在 service层的方法 上加@Transactional 做的的事务,这样在service事务还提交不了?我对spring的理解不够深,我以为把这个注解加在哪个方法上,事务就控制到这个层了呢 |
|
DataAccessException e这个异常是 spring把SqlException异常转化过来的,报错是唯一索引冲突,所以底层就是SqlException,但是Spring会把他转为DataAccessException 异常,我之前是写的 Exception的 效果是一样 |
|
你catch(Exception e)的怎么可能捕获不到,除非你balanceSourceService.save方法里面又自己try catch了 |
|
确实是捕获不到,我就在疑惑这个问题 ,http://bbs.csdn.net/topics/390050093?page=1#post-398522654这个论坛也是在说这个问题,最后也灭出来答案,;;刚才 11楼这样说的 ,我在试试:按你所描述的,应该是在service层事物没有提交,所以,延迟到COntrol层才报错,你检查下你事物配置。你可以手动提交先验证下,再做修改; |
|
40分 |
楼主是service里面又调用了balanceSourceService.save是吧,那你这个service上是不是已经有事务了如果有,那么balanceSourceService.save上是不是也有事务标识,如果balanceSourceService.save上也有事务标识而调用balanceSourceService.save的service的方法上也有事务标识的话,那么这个事务事务的传播方式如果balanceSourceService.save不是Propagation.REQUIRES_NEW的话就会出现这个问题,因为不新开一个事务的话,两个都是用同一个事务,balanceSourceService.save方法运行完成了,是不会提交的,只有上层的service调用成功后才会提交的,而你这个索引的异常是要事务提交到数据库才会出现的,所以你才捕获不到,如果你balanceSourceService.save方法上的事务传播改为Propagation.REQUIRES_NEW的话就能捕获到了 |
您说的这个点我都没考虑到,确实是会出现这样的情况的 ,我在事务上的控制是在放在方法上的 ,没有在类上做事务的控制,目前是只有在service的那个方法上加的有事务如下所示: public class BalanceInterfaceImpl{ @Transactional public void payFees(){ .... .... balanceSourceService.save(source); } } balanceSourceService.save(source)这是另外一个类中的方法,并且这个方法我没有去手动的在方法上加事务,您说这是几个事务,我理解的只有一个(对事务的原理理解的不是很好),请指点!谢谢您了 |
|
额,我大概明白点了,但是问题会又出来了,假如我balanceSourceService.save使用REQUIRES_NEW这种事务传播方式,那么当balanceSourceService.save成功提交但是在上层的service方法中有异常了 需要回滚 此时我balanceSourceService.save的事务已提交是回滚不了的了 |
|
try {
balanceSourceService.save(source); }catch (Exception e) { e.printStackTrace(); } 这段代码中 事物是在哪 在Service上还是在你这个方法这边? |
|
你这个 唯一索引、是主键、有事索引是吗?
要是的话、你先把唯一索引的条件去掉、 看能否、save成功? 我怀疑是唯一索引的问题、
|
|
数据库中的字段 是主键有事唯一索引 就是会冲突的、
|
|
不是,主键和组合的唯一索引分开了的 ,就是事务的问题导致的 ,现在明白了 |
|
你的事务在service层没有commit,所以只能在上一层处理
|