Spring JdbcTemplate释放连接
前言
Spring JdbcTemplate在通过DataSourceUtils管理Connection,DataSourceUtils通过ConnectionHolder管理Connection。并且将ConnectionHolder保存在ThreadLocal,所以是线程安全的。
详见org.springframework.jdbc.datasource.DataSourceUtils#getConnection
问题
但是在释放的时候,ConnectionHolder的实现类SimpleConnectionHandle的releaseConnection缺失一个空方法。导致该Connection出现问题后无法更换Connection。比如,使用数据库连接池,重启数据库后SQL会一直执行失败。
解决方法
org.springframework.jdbc.datasource.DataSourceUtils#doGetConnection方法中通过TransactionSynchronizationManager.getResource(dataSource);返回ConnectionHolder,如果返回null则重新创建,debug下去,发现在org.springframework.transaction.support.TransactionSynchronizationManager#doGetResource方法里面,通过((ResourceHolder) value).isVoid()判断是否值为空,如果isVoid返回true,则删除当前线程中的ConnectionHolder。所以想办法将isVoid设置为true,就可以实现释放当前Connection。
Exception中处理代码如下:
public static void released(JdbcTemplate jdbcTemplate) { try { ConnectionHolder holder = (ConnectionHolder) TransactionSynchronizationManager.getResource(jdbcTemplate.getDataSource()); holder.getConnection().close(); // set holder isVoid true holder.unbound(); } catch (SQLException e1) { e1.printStackTrace(); } }
写在最后
以上问题的分析和处理是通过debug下面的方法得出的,所以遇到问题查看源码确实是一种非常好的方法。
org.springframework.jdbc.core.JdbcTemplate#execute(org.springframework.jdbc.core.PreparedStatementCreator, org.springframework.jdbc.core.PreparedStatementCallback<T>)
推荐阅读
-
完美解决spring websocket自动断开连接再创建引发的问题
-
Spring引入外部属性文件配置数据库连接的步骤详解
-
JSP Spring中Druid连接池配置详解
-
Spring中的JDBCTemplate、Spring基于AOP的事务控制、Spring中的事务控制
-
【⭐】Java—Spring-—数据库操作—使用内置连接池,报读取不到驱动错误。Could not load JDBC driver class。
-
解决IntelliJ IDEA创建spring boot无法连接http://start.spring.io/问题
-
Spring Boot 整合 MyBatis 连接 Oracle数据库
-
com.alibaba.druid检测排查数据库连接数不释放定位代码
-
解决IDEA使用Spring Initializr创建项目时,无法连接到https://start.spring.io的问题
-
Spring boot 连接Redis实现HMSET操作