异常Not able to obtain connection的解决办法

本文分析了在使用Struts框架的DispatchAction时遇到的一个常见异常,详细解释了异常产生的原因及解决方案,指出在Action中避免定义非只读的全局变量的重要性。
 最近在练兵的时候碰到这个问题,在网上搜罗了一大遍,碰到这个问题的网友还真不少,在此做个备忘,
 
也分析一下出现这种异常的原因。
 
  我的问题出现在Action中,我用的Action类型为DispatchAction,DispatchAction的特点就是通过配
 
置Action标签的parameter为method,然后在Action中直接定义多个业务方法,不同业务调用的是同一个
 
Action,只要加一个method的参数(参数值即为此业务方法在Action中的方法名)即可,调用的URL类似为:
 
**Action.do?method=setManageRoles,关于DispatchAction我就不多讲了,不清楚的可以参考Struts的
 
相关书籍和资料。
 
以下是我报异常的代码:

package struts.action;
import manage.UserManage;
import ..........
 
public class RolesModifyAction extends DispatchAction {
 
 //全局变量
 UserManage um = new UserManage();
 
 RoleDao dao = new RoleDao();
 
 String page = "";
 
// 业务方法一
 public ActionForward setManageRoles(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response) {
 
    for (int j = 0; j < mbrand.length; j++) {

        UserRole userrole = um.getUserRoleByUserName(mbrand[j]);

        userrole.setRoleid(1);

        dao.saveOrUpdate(userrole);
  
     .........

    }

     return mapping.findForward(page);

 }
 
 public ActionForward setAgentRoles(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response) {   

    .........  

  return mapping.findForward(page); 
 
 }
 
        public ActionForward setNormalRoles(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response) {

     .........  

  return mapping.findForward(page);
  
 }
 
  以上代码为一个设置用户权限的Action,包含三个业务方法,在Action的开头我定义了这三个业务方法
 
共用的几个全局变量,这样看也没什么不妥,并且在执行时,第一次总能执行成功,但接着执行第二次的时候
 
就会抛出异常。尝试调试了很多次,但都未能解决,最后只有请同事帮忙了,同事一看就指出了死结:在
 
Ation中要避免定义全局变量,要定义都只能定义只读类型的,如常量,因为一个请求到达Action后即实例化
 
这些变量,并只实例化一次,这样以上代码的其它业务方法调用时将不会再实例化。
 
总结:
 
  抛这个异常主要原因是在进行数据库操作时获取不到可用的连接,也就是说session已经关闭了。上面的
 
代码在执行第一次后(dao.saveOrUpdate(userrole);)已将session关闭了,注:我是利用过滤器控制事务的
 
提交与session的关闭的,每执行完一次请求,过滤器自动提交事务,然后关闭session。

解决办法就是将所有全局变量取消,全部移入至每个业务方法内,这样就没问题啦。因此若出现此异常就一定
 
是某段操作数据库的代码出现问题了,这段代码将数据库连接提前关闭了,只要揪出这段代码,再结合你的
 
相关业务逻辑调整就可解决了。
<think> 我们被要求解决Spring Boot中出现的"failed to obtain JDBCConnection nested exception is org.apache.tomcat.jdbc.pool"异常。这个异常通常与数据库连接有关,可能是由于数据库连接池无法获取到数据库连接。 根据引用内容,虽然引用的主要问题是关于Swagger和Druid的,但我们可以从中提取一些通用的解决思路。例如,引用[4]提到了由于版本不兼容导致的问题,引用[5]提到了依赖问题可能导致启动失败。此外,我们还可以结合常见的数据库连接问题处理步骤。 常见原因: 1. 数据库连接配置错误(如URL、用户名、密码) 2. 数据库服务未启动或网络不通 3. 数据库连接池配置不当(如最大连接数不足,等待超时时间太短) 4. 数据库驱动版本不兼容 5. 数据库连接泄漏(连接未正确关闭) 解决方案: 1. **检查数据库配置**:确保application.properties(或application.yml)中的数据库连接信息正确,包括URL、用户名和密码。 - 示例配置: ``` spring.datasource.url=jdbc:mysql://localhost:3306/mydb?useSSL=false&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=123456 spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver ``` 2. **确认数据库服务状态**:检查数据库是否已启动,并且可以通过网络访问。 3. **调整连接池配置**:增加最大连接数或调整超时设置。例如,使用Tomcat连接池时,可以配置: ``` spring.datasource.tomcat.max-active=50 spring.datasource.tomcat.max-wait=20000 ``` 4. **检查数据库驱动版本**:确保使用的数据库驱动与数据库版本兼容。例如,MySQL 8.x需要使用`com.mysql.cj.jdbc.Driver`,并且URL中需要指定时区(如`serverTimezone=UTC`)。 5. **检查连接泄漏**:如果连接没有被正确关闭,可能会导致连接池耗尽。可以开启连接池的监控和泄漏检测。例如,对于Tomcat连接池: ``` spring.datasource.tomcat.test-on-borrow=true spring.datasource.tomcat.validation-query=SELECT 1 ``` 6. **检查依赖冲突**:如果项目中引入了多个数据库连接池(如HikariCP和Tomcat JDBC Pool),可能会冲突。Spring Boot默认使用HikariCP,如果使用Tomcat连接池,需要排除HikariCP依赖。 7. **查看日志**:详细日志可能提供更多线索,可以开启DEBUG日志级别来查看数据库连接池的详细日志。 由于引用中没有直接提到这个异常,我们主要基于常见的解决方法给出方案。但是,引用[4]提到了版本不兼容问题,引用[5]提到了依赖问题,所以我们也要考虑版本兼容性和依赖问题。 因此,补充两点: 8. **检查依赖版本**:确保Spring Boot的版本与数据库驱动和连接池的版本兼容。可以在Spring Boot官方文档中查看推荐的依赖版本。 9. **清理和重新构建**:如果怀疑是构建问题,可以尝试清理和重新构建项目(如删除`target`目录,重新运行`mvn clean install`)。引用[5]中提到了通过删除垃圾文件(可能是本地Maven仓库中的损坏依赖)来解决类似问题。 步骤总结: 1. 验证数据库配置。 2. 检查数据库服务。 3. 调整连接池参数。 4. 检查驱动版本。 5. 检查连接泄漏。 6. 排除依赖冲突。 7. 查看详细日志。 8. 检查依赖版本兼容性。 9. 清理和重构项目。 相关问题: 1. 如何配置Spring Boot中的数据库连接池参数? 2. 如何监控Spring Boot应用的数据库连接池状态? 3. 如何解决数据库连接泄漏问题? </think> ### Spring Boot中"failed to obtain JDBCConnection"异常的解决方案 该异常表明应用无法从数据库连接池获取有效连接,通常由以下原因引起: #### 1. **数据库配置错误** - **检查连接参数**:确保`application.properties`中配置正确: ```properties spring.datasource.url=jdbc:mysql://localhost:3306/your_db?useSSL=false spring.datasource.username=your_user spring.datasource.password=your_password spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver ``` - **验证网络可达性**:使用`telnet localhost 3306`测试数据库端口连通性 #### 2. **连接池配置问题** - **增加连接池容量**: ```properties spring.datasource.tomcat.max-active=50 # 最大连接数 spring.datasource.tomcat.max-wait=20000 # 等待超时(ms) spring.datasource.tomcat.validation-query=SELECT 1 # 心跳检测 ``` - **添加连接验证**(防空闲断开): ```properties spring.datasource.tomcat.test-while-idle=true spring.datasource.tomcat.time-between-eviction-runs-millis=30000 ``` #### 3. **驱动版本不兼容**(常见于MySQL 8.x) - **更新JDBC驱动**: ```xml <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> <!-- 匹配数据库版本 --> </dependency> ``` - **检查时区配置**:在URL中添加`&serverTimezone=Asia/Shanghai` #### 4. **数据库服务问题** - 重启数据库服务:`sudo systemctl restart mysql` - 检查连接数限制:`SHOW VARIABLES LIKE 'max_connections';` - 验证用户权限:`GRANT ALL PRIVILEGES ON your_db.* TO 'user'@'%';` #### 5. **依赖冲突** - 执行依赖树分析:`mvn dependency:tree -Dverbose` - 排除旧版本驱动(如发现多个JDBC驱动): ```xml <exclusions> <exclusion> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </exclusion> </exclusions> ``` #### 6. **连接泄漏排查** - 启用连接监控: ```properties spring.datasource.tomcat.remove-abandoned=true spring.datasource.tomcat.remove-abandoned-timeout=60 ``` - 使用Druid监控(推荐): ```java @Bean public ServletRegistrationBean<StatViewServlet> druidServlet() { return new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*"); } ``` > **优先操作顺序**: > 1. 校验基础配置 → 2. 检查数据库状态 → 3. 升级驱动版本 → 4. 调整连接池参数 → 5. 排查依赖冲突 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值