程序如果长时间不进行数据库操作,那么数据源中的 Connection 很可能已经断开。其原因有可能是防火墙,或者连接的数据库设置的超时时间。这里使用的是 C3P0 连接 oracle 数据库,引起的异常信息为:
?
?
org.springframework.transaction.TransactionSystemException: Could not roll back Hibernate transaction; nested exception is org.hibernate.TransactionException: rollback failed
at org.springframework.orm.hibernate4.HibernateTransactionManager.doRollback(HibernateTransactionManager.java:503)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:845)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionManager.java:822)
at org.springframework.transaction.interceptor.TransactionAspectSupport.completeTransactionAfterThrowing(TransactionAspectSupport.java:411)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:114)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
at com.platform.dao.TasksDAO$$EnhancerByCGLIB$$abcb28f5.getTaskById(<generated>)
?
at com.platform.manager.TasksManager.getTaskById(TasksManager.java:287)
at com.platform.manager.TasksManager.checkResult(TasksManager.java:300)
at com.platform.timer.TimerBase.tasksListener(TimerBase.java:149)
at com.platform.timer.TimerBase.run(TimerBase.java:81)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
Caused by: org.hibernate.TransactionException: rollback failed
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.rollback(AbstractTransactionImpl.java:215)
at org.springframework.orm.hibernate4.HibernateTransactionManager.doRollback(HibernateTransactionManager.java:500)
... 15 more
Caused by: org.hibernate.TransactionException: unable to rollback against JDBC connection
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doRollback(JdbcTransaction.java:167)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.rollback(AbstractTransactionImpl.java:209)
... 16 more
Caused by: java.sql.SQLException: 关闭的连接
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:111)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:145)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:207)
at oracle.jdbc.driver.PhysicalConnection.rollback(PhysicalConnection.java:1160)
at com.alibaba.china.jdbc.proxy.simple.ConnectionProxy.rollback(ConnectionProxy.java:228)
at com.mchange.v2.c3p0.impl.NewProxyConnection.rollback(NewProxyConnection.java:855)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doRollback(JdbcTransaction.java:163)
... 17 more
?
异常抛出的地方为 Spring 的事务管理 transactionManager,而并非程序代码。即便捕捉到异常,使用 sessionFactory.openSession 也会抛出如下异常:
?
?
org.springframework.transaction.TransactionSystemException: Could not roll back Hibernate transaction; nested exception is org.hibernate.TransactionException: rollback failed
at org.springframework.orm.hibernate4.HibernateTransactionManager.doRollback(HibernateTransactionManager.java:503)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:845)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionManager.java:822)
at org.springframework.transaction.interceptor.TransactionAspectSupport.completeTransactionAfterThrowing(TransactionAspectSupport.java:411)
?
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:114)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622)
?
at com.platform.dao.TasksDAO$$EnhancerByCGLIB$$abcb28f5.getTaskByNewSession(<generated>)
at com.platform.manager.TasksManager.checkResult(TasksManager.java:303)
at com.platform.timer.TimerBase.tasksListener(TimerBase.java:149)
at com.platform.timer.TimerBase.run(TimerBase.java:81)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)
Caused by: org.hibernate.TransactionException: rollback failed
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.rollback(AbstractTransactionImpl.java:215)
?
at org.springframework.orm.hibernate4.HibernateTransactionManager.doRollback(HibernateTransactionManager.java:500)
... 14 more
Caused by: org.hibernate.TransactionException: unable to rollback against JDBC connection
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doRollback(JdbcTransaction.java:167)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.rollback(AbstractTransactionImpl.java:209)
... 15 more
Caused by: java.sql.SQLException: Io 异常: Software caused connection abort: recv failed
?
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:111)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:145)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:254)
at oracle.jdbc.driver.T4CConnection.doRollback(T4CConnection.java:577)
at oracle.jdbc.driver.PhysicalConnection.rollback(PhysicalConnection.java:1163)
at com.alibaba.china.jdbc.proxy.simple.ConnectionProxy.rollback(ConnectionProxy.java:228)
at com.mchange.v2.c3p0.impl.NewProxyConnection.rollback(NewProxyConnection.java:855)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doRollback(JdbcTransaction.java:163)
... 16 more
?
解决的办法是:
?
c3p0 自定义配置:
?
?
<!--如果设为true那么在取得连接的同时将校验连接的有效性。若检测为无效,则自动重新获取连接。Default: false -->
<prop key="testConnectionOnCheckin">true</prop>
?
?
<!--定义所有连接测试都执行的测试语句。在使用连接测试的情况下这个一显著提高测试速度。 注意: 测试的表必须在初始数据源的时候就存在。Default:?null -->
<prop key="preferredTestQuery">select 1 from dual</prop>
?
https://community.jboss.org/wiki/HowToConfigureTheC3P0ConnectionPool
testConnectionOnCheckout?Must be set in c3p0.properties, C3P0 default: false
Don't use it, this feature is very expensive. If set to true, an operation will be performed at every connection checkout to verify that the connection is valid. A better choice is to verify connections periodically using c3p0.idleConnectionTestPeriod.
?
参考:
http://my.oschina.net/tianzimensheng/blog/65225
http://www.cnblogs.com/younes/archive/2012/06/01/2529483.html
http://www.cnblogs.com/safeking/archive/2007/02/01/637067.html
?
?
?
?
?
?
?