java.sql.SQLException: 关闭的连接 解决办法

本文详细介绍了在使用C3P0连接Oracle数据库时遇到的问题,即长时间未进行数据库操作导致连接断开引发的Spring事务异常。通过配置C3P0参数,特别是idleConnectionTestPeriod、testConnectionOnCheckin和automaticTestTable,解决了异常问题。

程序如果长时间不进行数据库操作,那么数据源中的 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 自定义配置:

 

 

 

<!-- 数据库连接声明 -->

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"

destroy-method="close">

<property name="driverClass" value="com.alibaba.china.jdbc.SimpleDriver" />

<!-- <property name="driverClass" value="oracle.jdbc.OracleDriver" /> -->

<property name="jdbcUrl" value="jdbc:oracle:thin:@202.116.70.180:61166:orcl" />

<!-- 每60秒检查所有连接池中的空闲连接。Default: 0 -->

<property name="idleConnectionTestPeriod" value="60" />

  <!--如果设为true那么在取得连接的同时将校验连接的有效性。Default: false -->

<property name="testConnectionOnCheckin" value="true" />

<!--c3p0将建一张名为Test的空表,并使用其自带的查询语句进行测试。如果定义了这个参数那么 属性preferredTestQuery将被忽略。你不能在这张Test表上进行任何操作,它将只供c3p0测试 

使用。Default: null -->

<property name="automaticTestTable" value="Test" />

 

<property name="properties">

<props>

<prop key="clientEncoding">GBK</prop>

<prop key="serverEncoding">CP1252</prop>

<prop key="user">WDS</prop>

 <prop key="password">HelloOracle</prop> 

</props>

</property>

</bean>

 

配置项一定要作为 <bean> 的子元素,而不能做为 <properties> 的子元素,否则不起作用。

 

 

参考:

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

<think>我们面对的是一个由sun.org.mozilla.javascript.internal.WrappedException包装的java.sql.SQLException,具体错误是ORA-20002。根据之前的讨论,我们知道ORA-20002是Oracle数据库中的一个自定义错误,通常由数据库中的存储过程、函数、触发器等PL/SQL代码中的业务逻辑错误引发(例如,通过RAISE_APPLICATION_ERROR(-20002, '错误信息')抛出)。因此,解决此问题需要从数据库层面和应用程序层面同时入手。 ### 解决步骤: 1. **确定错误来源的具体位置**: - 由于ORA-20002是自定义错误,我们首先需要查看数据库端的错误堆栈或应用程序捕获的完整异常信息,以确定是哪个数据库对象(存储过程、函数、触发器等)抛出了该错误。 - 检查应用程序日志,找到引发异常SQL语句或调用的存储过程。 2. **检查数据库中的自定义代码**: - 登录到Oracle数据库,查询数据字典(如`USER_SOURCE`)来查找抛出ORA-20002的代码位置。例如: ```sql SELECT name, type, line, text FROM user_source WHERE UPPER(text) LIKE '%RAISE_APPLICATION_ERROR(-20002%'; ``` 这将返回所有包含`RAISE_APPLICATION_ERROR(-20002, ...)`的存储过程、函数或包体的源代码位置。 3. **分析触发条件**: - 找到抛出错误的代码位置后,分析其业务逻辑,确定在什么条件下会触发该错误。通常,自定义错误会包含特定的错误消息,这些消息会提供线索(例如,“账户余额不足”、“无效的输入参数”等)。 - 例如,在存储过程中可能有如下代码: ```sql IF p_amount < 0 THEN RAISE_APPLICATION_ERROR(-20002, '金额不能为负数'); END IF; ``` 那么当传入的金额参数为负数时,就会触发ORA-20002。 4. **检查应用程序传入的参数**: - 在应用程序中,检查调用该数据库对象时传入的参数是否符合业务规则。可以使用日志记录参数值,或使用调试工具进行跟踪。 5. **修改代码或业务逻辑**: - 根据分析结果,修改数据库端的PL/SQL代码或应用程序传入的参数,以避免触发该错误条件。 - 如果该错误是业务规则的一部分(例如,要求用户必须满足某些条件),则应在应用程序中提前校验,避免触发数据库错误。 6. **应用程序异常处理**: - 在Java应用程序中,应该捕获SQLException并检查错误代码(ORA-20002),然后根据业务需求进行相应的处理(如给用户友好的提示)。 - 示例代码: ```java try { // 执行数据库操作 } catch (SQLException e) { if (e.getErrorCode() == 20002) { // 注意:Oracle错误代码在SQLException中是正数 // 处理自定义错误 String errorMessage = e.getMessage(); // 解析错误消息,给用户友好提示 System.err.println("业务错误: " + errorMessage); } else { // 其他错误处理 } } ``` ### 注意事项: - 由于错误是通过`sun.org.mozilla.javascript.internal.WrappedException`包装的,这表明可能是在JavaScript引擎(如Rhino)中执行的Java代码抛出的。因此,需要检查JavaScript代码中调用Java方法的逻辑,确保参数传递正确。 - 另外,注意数据库事务的处理。如果抛出ORA-20002,当前事务可能已经被回滚,应用程序需要处理事务回滚后的逻辑。 ### 示例场景: 假设在Oracle数据库中有一个存储过程`PROC_TRANSFER`,其中包含如下代码: ```sql CREATE OR REPLACE PROCEDURE PROC_TRANSFER(p_from_account NUMBER, p_to_account NUMBER, p_amount NUMBER) AS v_balance NUMBER; BEGIN SELECT balance INTO v_balance FROM accounts WHERE account_id = p_from_account; IF v_balance < p_amount THEN RAISE_APPLICATION_ERROR(-20002, '账户余额不足'); END IF; -- 其他操作 END; ``` 当Java应用程序调用此存储过程,并传入的`p_amount`大于账户余额时,就会抛出ORA-20002错误。解决方法可以是: 1.Java调用存储过程之前,先查询账户余额,确保余额充足。 2. 或者在捕获到ORA-20002错误时,提示用户“余额不足”。 ### 总结: 解决ORA-20002错误的关键在于定位数据库中的自定义错误抛出点,理解其业务规则,并确保应用程序传入的数据满足这些规则。同时,应用程序应妥善处理该异常,提供友好的用户反馈。 §§相关问题§§ 1. 如何在Oracle数据库中查找引发ORA-20002错误的存储过程或触发器? 2.Java应用程序中,如何针对不同的Oracle自定义错误代码(如ORA-20002)进行异常处理? 3. 如何优化数据库自定义错误消息,以便于在应用程序中直接展示给用户? 4. 在调用Oracle存储过程时,如何避免触发自定义业务错误? 5. 当ORA-20002错误发生时,如何确保数据库事务正确回滚? </think>要解决`sun.org.mozilla.javascript.internal.WrappedException: Wrapped java.sql.SQLException: java.sql.SQLException: ORA-20002`错误,请按以下步骤操作(结合引用内容分析): ### 解决步骤: 1. **定位数据库自定义错误源** - ORA-20002是Oracle自定义错误,需检查数据库中的PL/SQL对象: ```sql SELECT text FROM all_source WHERE UPPER(text) LIKE '%RAISE_APPLICATION_ERROR(-20002%'; ``` - 此查询可定位抛出该错误的存储过程/触发器[^1] 2. **检查传入参数有效性** - 常见原因:存储过程接收到无效参数(如空值、格式错误等) - 示例:若存储过程要求正整数参数,传入负数会触发ORA-20002 3. **排查资源泄漏风险** - 参考引用[2],确保及时关闭数据库资源: ```java try (PreparedStatement ps = conn.prepareStatement(sql); ResultSet rs = ps.executeQuery()) { // 处理结果集 } // 自动关闭资源(Java 7+语法) ``` 4. **验证SQL语法合法性** - 参考引用[3][4],ORA-01747表明可能存在: - 列名使用Oracle保留字(如`INDEX`) - 字段名与表名冲突 - 解决方案:使用带引号的标识符或重命名 5. **分析完整错误堆栈** - 在日志中搜索完整的错误链: ``` Caused by: java.sql.SQLException: ORA-20002: 具体错误描述 at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:450) ... ``` - 定位触发错误的SQL语句和参数值 ### 关键检查点: | 检查方向 | 具体操作 | 预期结果 | |---------|---------|---------| | **数据库对象** | 检查`RAISE_APPLICATION_ERROR`调用 | 确定错误触发条件 | | **应用程序** | 记录SQL执行前参数值 | 验证参数合法性 | | **连接配置** | 检查SID/service_name配置[^1] | 排除连接层错误 | | **资源管理** | 监控`V$OPEN_CURSOR`[^2] | 确保游标及时关闭 | ### 预防措施: ```java // 自定义异常处理器示例 try { // 执行数据库操作 } catch (SQLException e) { if (e.getErrorCode() == 20002) { logger.error("业务规则冲突: " + e.getMessage()); // 返回友好错误提示 } } ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值