irpas技术客

Could not open JDBC Connection for transaction; nested exception is com.alibaba.

未知 4720

一、错误概述

项目中使用了阿里的 Druid 数据库,刚开始很正常,后来发现出现了问题,问题如下:

org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is com.alibaba.druid.pool.DataSourceClosedException: dataSource already closed at Fri Jul 08 16:14:13 GMT+08:00 2022 ?? ?at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:309) ?? ?at org.springframework.transaction.support.AbstractPlatformTransactionManager.startTransaction(AbstractPlatformTransactionManager.java:400) ?? ?at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:373) ?? ?at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:595) ?? ?at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:382) ?? ?at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ?? ?at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ?? ?at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:753) ?? ?at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:698) ?? ?at java.base/java.util.TimerThread.mainLoop(Timer.java:566) ?? ?at java.base/java.util.TimerThread.run(Timer.java:516) Caused by: com.alibaba.druid.pool.DataSourceClosedException: dataSource already closed at Fri Jul 08 16:14:13 GMT+08:00 2022 ?? ?at com.alibaba.druid.pool.DruidDataSource.getConnectionInternal(DruidDataSource.java:1113) ?? ?at com.alibaba.druid.pool.DruidDataSource.getConnectionDirect(DruidDataSource.java:1017) ?? ?at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:997) ?? ?at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:987) ?? ?at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:103) ?? ?at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:265) ?? ?... 13 common frames omitted

?日志比较多,重点有以下几个:

Could not open JDBC Connection for transaction; nested exception is com.alibaba.druid.pool.DataSourceClosedException: dataSource already closed at Fri Jul 08 16:14:13 GMT+08:00 2022

?Caused by: com.alibaba.druid.pool.DataSourceClosedException: dataSource already closed at Fri Jul 08 16:14:13 GMT+08:00 2022

?其他的我们截图看看:

?上图打码的地方是公司的dao层查数据库的代码。

意思很明白了,就是因为在进行查询的时候,连接已经关闭了,而且会一直刷出这样的日志。

二、网友的给出的原因与解决方案

综合网上大家的意见,可能原因主要有以下几点:

1.异步线程问题 你可能使用了异步线程去访问数据库,异步线程是不由spring管理也就是说,spring可以在异步线程未执行完就会进行容器关闭 当异步线程执行到获取数据库的时候就会报错

?博主给的答案是:

怎么才能彻底消除这个错误没有找到完美的解决方法,只要DataSource不进行重新注册,或者重新注册后再刷新相关的DAO引用的实例可暂时不出现这个问题了

?参考:Druid连接池自动关闭

2.多线程批量问题

其实这个答案和上面一个的说法一致,不过这个给出了解决方案:

?多线程批量处理的时候只需要在service方法上加上@transactional(rollbackFor = Exception.class)就行了,mybatis就不会每次执行完sql后closing sql session了

3. 热部署问题

是否在定时器中手动获取了 DataSource,然后使用后关闭了或者用完后长期不再用被连接池自动关闭了?

答案是:发现不修改代码的时候,不会发生异常,修改代码之后触发热加载,然后就中断了链接,所以就报出那个错误。

这是网友的答案。

4.自动关闭问题

应该就是长时间不用,Druid自动关闭的问题。

这也是网友给出的可能性答案。

下面的也是网友的答案:

如果使用 jfinal 提供的 ActiveRecord 或者 Db + Record 操作数据库就不会出现此问题,自行得到 DataSource 或 Connection 的代码就需要开发者自己管理好这两个对象。

这个我没有尝试。

.setTestOnBorrow(false) .setTestOnReturn(false)

都改成 true。有网友说这个答案。

我试了试,没有什么卵用。

三、我的错误原因

最终我发现可能的原因是:

我这项目启动的时候会有?@PostConstruct 注解初始化 redis 数据,通过多线程方式去处理,然后还会有定时任务定时刷新。而项目中有热部署,只要改动代码之后就会自动重启项目,然后就会出现了上述的错误。

如果我改动了代码,不让它热部署启动,我手动重启,或者先关闭项目然后再启动,就不会报这个错误了。

所以,我这边最终的原因就是热部署的问题,我的热部署不是使用的devtools,而是idea上有一个配置,改动配置之后就会热部署,但是我忘记改动哪个地方了。以后想起来了,再来修改文章。

四、奇怪的问题

我们同一套代码,都是Git上最新代码,但是我同事的代码就会报上面这个错误,我的就好的,他的没有热部署。最终发现的原因竟然是:

package com.xxx.common.util; import com.xxx.common.file.SftpAuthority; import com.xxx.ytec.common.file.SftpService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Component @Order(1) public class FileCommandLineRunner implements CommandLineRunner { private static final Logger LOGGER = LoggerFactory.getLogger(FileCommandLineRunner.class); @Autowired private SftpService sftpService; @Override public void run(String... args) throws Exception { LOGGER.info("---------FileCommandLineRunner下载文件开始---------"); SftpAuthority root = new SftpAuthority("root", "192.168.0.100", 22); root.setPassword("123456"); sftpService.createChannel(root); sftpService.downloadFile(root, "/xxx/file/Data.csv", "C:\\Users\\Data.csv"); LOGGER.info("---------FileCommandLineRunner下载文件成功---------"); } }

?因为这一套代码,他那里报了我们上面说的错,这个代码怎么与数据源连接有关呢?这个代码就是在项目启动的时候自动执行里面的代码,里面的逻辑就是通过sftp从服务器上下载文件的。

现在他的报错如下:

?这个问题是很奇怪的,在我的电脑上没问题,在他那就会报错,只好把这个代码注释掉了。本来这个代码是我写给他测试下载文件的,也不会用到。

问题不算完美解决,暂时先这样吧!


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #could #not #OPEN #jdbc #Connection #for #Transaction #NESTED