使用Spring、hibernate 框架,捕获不到主键冲突的异常

J2EE 码拜 9年前 (2015-09-10) 3714次浏览

 

我们项目使用的是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)
#1
上面的那段代码 是我为了 在最底层捕获异常加的, 那个save是我封装了下  Hibernate的save方法,没有做任何处理的,同样捕获不到
#2
1112-100-20798257826887681-2 用这个去你的表里查一下,看有没有2个
#3

回复1楼:

你确定没进catch吗

#4
什么是最外层报错,异常捕获友好处理返回了么,异常打印在后台是可以的,出现在页面说明没处理
#5

回复2楼:

这是一种方法,先查在做处理,但是这个查和插入也会有那个极端的情况  在查的同时做了个插入的操作导致  索引冲突的异常吧

#6

回复3楼:

#7

回复5楼:

没看懂你的意思。 先查——判断——插入不是正常的么?

#8

回复7楼:

是的,一般的话 这个业务顺序是正常的,那为什么我在service的异常捕获不到,反而在我service的外层Controller层可以捕获到,这个不明白为什么

#9
你try catch写到service中怎么可能补货不到,你service的代码里面又try catch吗
#10

回复9楼:

没有的,在我service调用的那个save方法就是封装的hibernate的了,不知道为啥 在service层捕获不到,但是在service的外层也就是action层可以捕获到。

网上说 是spring把 SqlException 转换成了DataAccessException, 但是只能在service的外层可以捕获到 不知道为啥?

请您看下:http://bbs.csdn.net/topics/390050093?page=1#post-398522654

这个是网上之前的一个论坛,也是说这个问题的   请您看下,可能是我没说清楚

#11

10分

按你所描述的,应该是在service层事物没有提交,所以,延迟到COntrol层才报错,你检查下你事物配置。你可以手动提交先验证下,再做修改;
#12
你service里面没有try catch当然捕获不到了,你都是直接调用方法下去的,异常又没在service里面捕获,都是直接往上层抛出去的如果你在你的service.save方法里面做try catch肯定能捕获到的
#13

回复12楼:

其实我的这个方法就是在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

#14

回复13楼:

你只是捕获DataAccessException类型的异常,他抛的不是这种的异常你当然捕获不到了,你改成catch(Exception e)

#15

回复11楼:

我使用注解在 service层的方法 上加@Transactional  做的的事务,这样在service事务还提交不了?我对spring的理解不够深,我以为把这个注解加在哪个方法上,事务就控制到这个层了呢

#16

回复14楼:

DataAccessException e这个异常是 spring把SqlException异常转化过来的,报错是唯一索引冲突,所以底层就是SqlException,但是Spring会把他转为DataAccessException 异常,我之前是写的 Exception的  效果是一样

#17

回复16楼:

你catch(Exception e)的怎么可能捕获不到,除非你balanceSourceService.save方法里面又自己try catch了

#18

回复17楼:

确实是捕获不到,我就在疑惑这个问题 ,http://bbs.csdn.net/topics/390050093?page=1#post-398522654这个论坛也是在说这个问题,最后也灭出来答案,;;刚才 11楼这样说的 ,我在试试:按你所描述的,应该是在service层事物没有提交,所以,延迟到COntrol层才报错,你检查下你事物配置。你可以手动提交先验证下,再做修改;

#19

40分

回复18楼:

楼主是service里面又调用了balanceSourceService.save是吧,那你这个service上是不是已经有事务了如果有,那么balanceSourceService.save上是不是也有事务标识,如果balanceSourceService.save上也有事务标识而调用balanceSourceService.save的service的方法上也有事务标识的话,那么这个事务事务的传播方式如果balanceSourceService.save不是Propagation.REQUIRES_NEW的话就会出现这个问题,因为不新开一个事务的话,两个都是用同一个事务,balanceSourceService.save方法运行完成了,是不会提交的,只有上层的service调用成功后才会提交的,而你这个索引的异常是要事务提交到数据库才会出现的,所以你才捕获不到,如果你balanceSourceService.save方法上的事务传播改为Propagation.REQUIRES_NEW的话就能捕获到了

#20

回复19楼:

您说的这个点我都没考虑到,确实是会出现这样的情况的 ,我在事务上的控制是在放在方法上的 ,没有在类上做事务的控制,目前是只有在service的那个方法上加的有事务如下所示:

	public class BalanceInterfaceImpl{
		
		@Transactional
		public void payFees(){
			....
			....
			balanceSourceService.save(source);
		}
	}

balanceSourceService.save(source)这是另外一个类中的方法,并且这个方法我没有去手动的在方法上加事务,您说这是几个事务,我理解的只有一个(对事务的原理理解的不是很好),请指点!谢谢您了

#21

回复19楼:

额,我大概明白点了,但是问题会又出来了,假如我balanceSourceService.save使用REQUIRES_NEW这种事务传播方式,那么当balanceSourceService.save成功提交但是在上层的service方法中有异常了 需要回滚  此时我balanceSourceService.save的事务已提交是回滚不了的了

#22
try {

balanceSourceService.save(source);

}catch (Exception e) {

e.printStackTrace();

}

这段代码中 事物是在哪 在Service上还是在你这个方法这边?

如果你的事物没在save的时候提交 那么就不会报错

你那个错是事物提交的时候才报错的

如果你save没提交事物

你这里确实捕获不到异常吧

#23
你这个 唯一索引、是主键、有事索引是吗?

要是的话、你先把唯一索引的条件去掉、 看能否、save成功?

我怀疑是唯一索引的问题、

#24
数据库中的字段 是主键有事唯一索引 就是会冲突的、
#25

回复24楼:

不是,主键和组合的唯一索引分开了的 ,就是事务的问题导致的  ,现在明白了

#26
你的事务在service层没有commit,所以只能在上一层处理

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明使用Spring、hibernate 框架,捕获不到主键冲突的异常
喜欢 (0)
[1034331897@qq.com]
分享 (0)