DBCP错误:java.sql.SQLException: Already closed.

遇到这个错误,搜索了一下解决方法,经测试好用。
java.sql.SQLException: Already closed.
at org.apache.tomcat.dbcp.dbcp.PoolableConnection.close(PoolableConnection.java:84)
at org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.close(PoolingDataSource.java:181)
at com.lwjlaser.citation2DB.Citation.controller(Citation.java:84)
at com.lwjlaser.citation2DB.DealCitation.doPost(DealCitation.java:46)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
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 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:127)
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:298)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:852)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:619)


原因:You're probably running into the fact that MYSQL closes connections
which have been open "too long".
Probably if you make the request to the server again, you'll find that
it works because the connection is reopened.
解决方法:[color=red]One way to deal with this is to add the following to your context.xml
Resource:

validationQuery="select 1"[/color]

代价:This causes a very cheap test query to always be run first; if the
connection has been closed, this gets the failure, and
then a new connection is opened
<think>嗯,用户遇到了java.sql.SQLException: connection disabled的错误,这个问题看起来和数据库连接池有关。首先,我需要回忆一下常见的数据库连接问题。连接池中的连接如果长时间空闲,可能会被数据库服务器断开,而连接池并不知道这个情况,导致尝试使用已经失效的连接时抛出异常。 根据用户提供的引用内容,他们使用的是Spring 3.2和Hibernate 4,并且连接池配置可能有问题。引用[2]提到尝试过多个连接池但没有找到满意的解决方案,所以可能需要调整现有的连接池配置。 首先,我应该考虑连接池的配置参数。比如,验证连接是否有效的机制,例如testOnBorrow或testOnReturn,这些参数可以在获取或归还连接时执行验证查询,确保连接仍然有效。如果用户没有设置这些,连接池可能在不知情的情况下分配了已经关闭的连接,导致错误。 另外,连接的最大存活时间(maxLifetime)也是一个关键参数。如果数据库服务器设置了连接超时,而连接池的连接存活时间超过这个值,就会导致连接被服务器关闭。需要确保maxLifetime略小于数据库的超时设置。 还有空闲连接的验证,比如使用空闲连接检测(idle validation),定期检查空闲连接是否仍然有效。比如,在Tomcat JDBC连接池中,可以设置timeBetweenEvictionRunsMillis和minEvictableIdleTimeMillis来定期检查和驱逐无效连接。 此外,连接泄漏的检测也很重要。如果应用程序没有正确关闭连接,可能会导致连接泄漏,最终耗尽连接池。启用连接泄漏检测(如removeAbandonedTimeout)可以帮助回收这些连接。 用户可能需要检查他们的数据源配置,确保已经正确配置了验证查询、超时参数和泄漏检测。例如,在Tomcat JDBC连接池中,配置validationQuery为SELECT 1,并设置testOnBorrow=true。同时调整maxActive和minIdle以适应负载,避免连接过多或过少。 另外,数据库服务器的等待超时设置(如MySQL的wait_timeout)也需要检查,确保连接池的配置与之匹配,避免服务器主动关闭连接。如果数据库在远程,网络问题也可能导致连接中断,所以超时设置可能需要更短。 最后,可能需要升级连接池库到更现代的版本,比如HikariCP或Tomcat JDBC Pool,这些连接池有更好的管理和恢复机制。例如,HikariCP默认有较好的心跳机制来维持连接活性。 总结来说,解决方案需要从连接验证、超时设置、泄漏检测和连接池参数调优几个方面入手,确保连接池能够有效管理连接,及时剔除无效连接,避免使用已关闭的连接导致异常。</think>### 解决 `java.sql.SQLException: connection disabled` 的逐步方案 #### 1. **检查连接池配置** 数据库连接池可能因空闲连接超时或未正确验证导致异常。需确保以下配置: - **验证查询(Validation Query)**:在获取连接前执行简单查询(如 `SELECT 1`)验证连接有效性。 - **最大存活时间(maxLifetime)**:设置略小于数据库服务器的超时时间(如 MySQL 默认 `wait_timeout=28800秒`)。 - **空闲连接检查**:定期检测并关闭无效空闲连接。 **示例配置(Tomcat JDBC Pool):** ```xml <bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource"> <property name="url" value="jdbc:mysql://remote-server:3306/db"/> <property name="username" value="user"/> <property name="password" value="password"/> <property name="validationQuery" value="SELECT 1"/> <!-- 验证查询 --> <property name="testOnBorrow" value="true"/> <!-- 借出时验证 --> <property name="maxActive" value="20"/> <property name="maxLifetime" value="28000"/> <!-- 单位:毫秒 --> <property name="timeBetweenEvictionRunsMillis" value="60000"/> <!-- 空闲检查间隔 --> <property name="minEvictableIdleTimeMillis" value="300000"/> <!-- 最小空闲时间 --> </bean> ``` #### 2. **处理数据库服务器超时设置** 若数据库服务器主动断开空闲连接(如 MySQL 的 `wait_timeout`),需确保连接池参数与之匹配: - 修改 MySQL 超时时间(需权限): ```sql SET GLOBAL wait_timeout = 28800; -- 单位:秒 ``` - 或调整连接池的 `maxLifetime` 小于 `wait_timeout`[^2]。 #### 3. **启用连接泄漏检测** 未正确关闭连接可能导致泄漏,最终触发异常。在连接池中启用泄漏检测: ```xml <property name="removeAbandonedTimeout" value="60"/> <!-- 单位:秒 --> <property name="removeAbandoned" value="true"/> ``` #### 4. **升级连接池库** 某些旧版连接池(如 DBCP 1.x)存在稳定性问题,建议切换至更现代的库: - **HikariCP**(推荐): ```java HikariConfig config = new HikariConfig(); config.setJdbcUrl("jdbc:mysql://remote-server:3306/db"); config.setUsername("user"); config.setPassword("password"); config.setConnectionTestQuery("SELECT 1"); // 验证查询 HikariDataSource dataSource = new HikariDataSource(config); ``` - **Tomcat JDBC Pool**(兼容 Spring 3.x): ```xml <dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-jdbc</artifactId> <version>9.0.0.M1</version> </dependency> ``` #### 5. **添加心跳机制** 通过定期发送查询保持连接活跃,例如使用调度任务: ```java @Scheduled(fixedRate = 300000) // 每5分钟执行一次 public void keepAlive() { try (Connection con = dataSource.getConnection(); Statement stmt = con.createStatement()) { stmt.execute("SELECT 1"); } catch (SQLException e) { // 处理异常 } } ``` ### 总结 通过 **验证连接有效性**、**调整超时参数**、**启用泄漏检测** 和 **使用可靠连接池**,可有效解决 `connection disabled` 错误。若问题持续,需检查网络稳定性或数据库服务器日志。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值