使用线程池就报Could not get JDBC Connection 主线程就没问题

ackerHu 2020-06-24 11:20:24
### The error occurred while executing a query
###Cause: org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is com.alibaba.druid.pool.DataSourceClosedException: dataSource already closed at Wed Jun 24 11:12:25 CST 2020

不使用线程池,使用主线程是OK的 ,使用线程池数据库就关闭了

下面的是数据库连接池的代码:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task.xsd">

<!-- 数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
destroy-method="close">
<!-- 基本属性 url、user、password -->
<property name="url" value="${platform.jdbc.url}" />
<property name="username" value="${platform.jdbc.username}" />
<property name="password" value="${platform.jdbc.password}" />
<property name="driverClassName" value="${platform.jdbc.driver}" />
<!-- 配置初始化大小、最小、最大 -->
<property name="initialSize" value="${platform.druid.initialSize}" />
<property name="minIdle" value="${platform.druid.minIdle}" />
<property name="maxActive" value="${platform.druid.maxActive}" />
<!-- 配置获取连接等待超时的时间 -->
<property name="maxWait" value="${platform.druid.maxWait}" />
<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
<property name="timeBetweenEvictionRunsMillis" value="${platform.druid.timeBetweenEvictionRunsMillis}" />
<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
<property name="minEvictableIdleTimeMillis" value="${platform.druid.minEvictableIdleTimeMillis}" />
<property name="validationQuery" value="${platform.druid.validationQuery}" />
<property name="testWhileIdle" value="${platform.druid.testWhileIdle}" />
<property name="testOnBorrow" value="${platform.druid.testOnBorrow}" />
<property name="testOnReturn" value="${platform.druid.testOnReturn}" />
<!-- 打开PSCache,并且指定每个连接上PSCache的大小 如果用Oracle,则把poolPreparedStatements配置为true,mysql可以配置为false。 -->
<property name="poolPreparedStatements" value="${platform.druid.poolPreparedStatements}" />
<property name="maxPoolPreparedStatementPerConnectionSize"
value="${platform.druid.maxPoolPreparedStatementPerConnectionSize}" />
<!-- 配置监控统计拦截的filters -->
<property name="filters" value="${platform.druid.filters}" />
</bean>

<!-- 配置SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:config/mybatis-config.xml" />
<property name="mapperLocations" value="classpath:sqlmap/*Mapper.xml" />
</bean>
<!-- 配置事务管理器 -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- enable transaction annotation support -->
<tx:annotation-driven transaction-manager="txManager" />

<!-- 配置mybatis需要扫描的包 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.dshamc.qa.platform.dao" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>
</beans>
...全文
12415 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
hiboys 2020-07-21
  • 打赏
  • 举报
回复
看看你的连接池支持多线程吗?需要配置支持多线程不? 担心一个连接对象分配给2个线程。第一个线程用完连接关闭,第二个线程再使用就 already closed
冰思雨 2020-07-20
  • 打赏
  • 举报
回复
楼主还是没有找到问题的原因啊。 你看看你的代码里面,有没有把一个数据库事务,用多线程来处理了? 一个数据库事务,要唯一分配给同一个线程来处理才行。如果一个数据库事务由多个线程来完成的话,需要特殊(设置)处理才行。
ackerHu 2020-07-16
  • 打赏
  • 举报
回复
引用 7 楼 冰思雨 的回复:
综合来看,凭经验猜测,应该是我上面提到的情况2,长时间未使用连接,连接被数据库关闭了。
楼主要将 testWhileIdle 打开(设置成true),当连接闲置时进行心跳唤醒操作(就是向数据库发送一个SQL来激活连接,比如 SELECT 1 之类的),然后,把闲置超时的时间,设置的短一点,一般来讲,这个闲置超时,是数据库空闲连接超时时间的三分之二。



问题是代码块只要用到线程池去操作数据源就关闭了 不用线程池去处理就是OK的 现在问题已经解决了 用线程池处理代码的时候我是本地main跑的 我把代码放到tomcat上就可以了 谢谢大家
冰思雨 2020-07-01
  • 打赏
  • 举报
回复
综合来看,凭经验猜测,应该是我上面提到的情况2,长时间未使用连接,连接被数据库关闭了。 楼主要将 testWhileIdle 打开(设置成true),当连接闲置时进行心跳唤醒操作(就是向数据库发送一个SQL来激活连接,比如 SELECT 1 之类的),然后,把闲置超时的时间,设置的短一点,一般来讲,这个闲置超时,是数据库空闲连接超时时间的三分之二。
冰思雨 2020-07-01
  • 打赏
  • 举报
回复
现象描述的场景不够具体。 你是在什么场景下出现的问题? 比如: 1. 连续两次使用数据库连接,第一次正常,第二次报错? 2. 长时间不使用连接,一旦使用就报错? 3. 有一个业务函数,执行时间很长,当调用这个业务函数的时候,就会报错? 上述三种情况,是哪一种? 情况1,说明你从连接池里面拿到了被关闭的连接,尝试 testOnBorrow=true 看看能否解决问题。 情况2,说明上时间未使用的连接被数据库关闭了,尝试 testWhileIdle=true。 情况3,说明业务函数的设计有问题,尝试持有数据库连接却不使用,造成连接被数据库关闭。更改业务逻辑,要把业务函数中,关于数据库的操作集中在一起封装成函数,运行封装后的函数时从连接池中拿连接,运行完后交还连接。
ackerHu 2020-06-29
  • 打赏
  • 举报
回复
可以非常感谢
ackerHu 2020-06-24
  • 打赏
  • 举报
回复
我的是mysql
ackerHu 2020-06-24
  • 打赏
  • 举报
回复
哪位大佬能帮忙看一下 定位了1天了 没看出问题来 需要我提供信息的留言一下 我来提供
ptclin_2007 2020-06-24
  • 打赏
  • 举报
回复
加我的QQ? 105009010
ptclin_2007 2020-06-24
  • 打赏
  • 举报
回复
帮你远程协助看看?
在Java下连接SQLite数据库 一、下载SQLite数据库的JDBC:http://www.zentus.com/sqlitejdbc/ 二、将下载到的包解压后得到jar包放到%JAVA_HOME%\lib下,并且将其添加到ClassPath系统环境变量中。一定要保证在类路径ClassPath中有该jar包,并且保证在JAVA库路径JAVA Library Path中有本地库Native Library(\workspace\"Web应用"\WebRoot\WEB-INF\lib\下最好也要加入该jar包)。"SQLite.JDBCDriver"作为JDBC的驱动程序类名。连接JDBC的URL格式为jdbc:sqlite:/path。这里的path为指定到SQLite数据库文件的路径,例如: jdbc:sqlite://dirA/dirB/dbfile jdbc:sqlite://DRIVE:/dirA/dirB/dbfile jdbc:sqlite://COMPUTERNAME/shareA/dirB/dbfile 三、下面是使用SQLite的两段代码以供参考: 代码段1: 1 import java.sql.*; 2 import org.sqlite.JDBC; 3 4 public class SQLiteTest { 5 public static void main(String[] args) { 6 try { 7 // The SQLite (3.3.8) Database File 8 // This database has one table (pmp_countries) with 3 columns (country_id, country_code, country_name) 9 // It has like 237 records of all the countries I could think of. 10 String fileName = "c:/pmp.db"; 11 // Driver to Use 12 // http://www.zentus.com/sqlitejdbc/index.html 13 Class.forName("org.sqlite.JDBC"); 14 // Create Connection Object to SQLite Database 15 // If you want to only create a database in memory, exclude the +fileName 16 Connection conn = DriverManager.getConnection("jdbc:sqlite:"+fileName); 17 // Create a Statement object for the database connection, dunno what this stuff does though. 18 Statement stmt = conn.createStatement(); 19 // Create a result set object for the statement 20 ResultSet rs = stmt.executeQuery("SELECT * FROM pmp_countries ORDER BY country_name ASC"); 21 // Iterate the result set, printing each column 22 // if the column was an int, we could do rs.getInt(column name here) as well, etc. 23 while (rs.next()) { 24 String id = rs.getString("country_id"); // Column 1 25 String code = rs.getString("country_code"); //

81,116

社区成员

发帖
与我相关
我的任务
社区描述
Java Web 开发
社区管理员
  • Web 开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧