DataUtils对Connection的获取、释放和关闭的操作学习
DataSourceUitls介绍
DataSourceUitls类位于org.springframework.jdbc.datasource包下,提供了很多的静态方法去从一个javax.sql.DataSource下获取JDBC Connection,并且提供了对Spring 事务管理的支持。
在JdbcTemplate类的内部,DataSourceUtils被多次使用。其实,我们还可以在代码中直接使用DataSourceUitls来操作Jdbc。
DataSourceUitls获取Connection
getConnection方法
内部实现
public static Connection getConnection(DataSource dataSource) throws CannotGetJdbcConnectionException {
try {
return doGetConnection(dataSource);
}
catch (SQLException ex) {
throw new CannotGetJdbcConnectionException("Failed to obtain JDBC Connection", ex);
}
catch (IllegalStateException ex) {
throw new CannotGetJdbcConnectionException("Failed to obtain JDBC Connection: " + ex.getMessage());
}
}
可以看出,通过传入一个指定的DataSource,可以获取一个Connection,获取过程由doGetConnection方法实现。如果抛出SQLException和IllegalStateException,则将其包装成CannotGetJdbcConnectionException,事实上也只能抛出SQLException和IllegalStateException这两种异常。通过查看CannotGetJdbcConnectionException的源代码,我们可以发现CannotGetJdbcConnectionException实际上是DataAccessException的子类,因此可以说,getConnection会将抛出的异常统一封装成Spring的DataAccessException。
doGetConnection方法
内部实现
public static Connection doGetConnection(DataSource dataSource) throws SQLException {
Assert.notNull(dataSource, "No DataSource specified");
ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) {
conHolder.requested();
if (!conHolder.hasConnection()) {
logger.debug("Fetching resumed JDBC Connection from DataSource");
conHolder.setConnection(fetchConnection(dataSource));
}
return conHolder.getConnection();
}
// Else we either got no holder or an empty thread-bound holder here.
logger.debug("Fetching JDBC Connection from DataSource");
Connection con = fetchConnection(dataSource);
if (TransactionSynchronizationManager.isSynchronizationActive()) {
logger.debug("Registering transaction synchronization for JDBC Connection");
// Use same Connection for further JDBC actions within the transaction.
// Thread-bound object will get removed by synchronization at transaction completion.
ConnectionHolder holderToUse = conHolder;
if (holderToUse == null) {
holderToUse = new ConnectionHolder(con);
}
else {
holderToUse.setConnection(con);
}
holderToUse.requested();
TransactionSynchronizationManager.registerSynchronization(
new ConnectionSynchronization(holderToUse, dataSource));
holderToUse.setSynchronizedWithTransaction(true);
if (holderToUse != conHolder) {
TransactionSynchronizationManager.bindResource(dataSource, holderToUse);
}
}
return con;
}
doGetConnection方法是用于实际操作获取Connection的核心方法。从源代码中可以得出,如果不存在与当前线程绑定的Connection,则新建一个全新的Connection,如果当前线程的事务同步处于活动状态,那么为刚刚创建的Connection添加Spring事务管理的支持;如果当前线程存在一个相应的Connection,那么则有当前的事务管理分配。
fetchConnection方法
fetchConnection是一个private方法,不对外公开,实际上是做了一个简单的功能:从当前的DastaSource新建一个Connection,如果新建失败,那么抛出IllegalStateException,提示不能获取一个新的Connection。
DataSourceUitls释放Connection
releaseConnection方法
内部实现
public static void releaseConnection(@Nullable Connection con, @Nullable DataSource dataSource) {
try {
doReleaseConnection(con, dataSource);
}
catch (SQLException ex) {
logger.debug("Could not close JDBC Connection", ex);
}
catch (Throwable ex) {
logger.debug("Unexpected exception on closing JDBC Connection", ex);
}
}
releaseConnection方法的具体实现由doReleaseConnection处理。如果抛出异常,仅仅是在日志中做debug处理,不会对外抛出。该方法的两个参数均存在NULL的情况,
如果con为NULL,则忽略本次调用;而另一个参数则被允许为NULL。
doReleaseConnection方法
内部实现
public static void doReleaseConnection(@Nullable Connection con, @Nullable DataSource dataSource) throws SQLException {
if (con == null) {
return;
}
if (dataSource != null) {
ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);
if (conHolder != null && connectionEquals(conHolder, con)) {
// It's the transactional Connection: Don't close it.
conHolder.released();
return;
}
}
logger.debug("Returning JDBC Connection to DataSource");
doCloseConnection(con, dataSource);
}
doReleaseConnection方法是真正释放了Connection的方法,与releaseConnection方法相比,则完成了对传入的两个参数的校验和抛出更底层的异常。在dataSource不为NULL的情况下,释放此ConnectionHolder保留的当前连接,使得该当前的Connection可以得到复用,对提供Jdbc操作的性能很有帮助。如果dataSource为null的情况下则选择直接关闭连接。
DataSourceUitls关闭Connection
doCloseConnection方法
内部实现
public static void doCloseConnection(Connection con, @Nullable DataSource dataSource) throws SQLException {
if (!(dataSource instanceof SmartDataSource) || ((SmartDataSource) dataSource).shouldClose(con)) {
con.close();
}
}
在doReleaseConnection方法中,我们已经得知当datasource为NULL的时候会执行doCloseConnection方法。事实上,只有dataSource没有实现org.springframework.jdbc.datasource.SmartDataSource接口的时候或者dataSource实现了org.springframework.jdbc.datasource.SmartDataSource接口且允许关闭的时候,在真正关闭了Connection。
org.springframework.jdbc.datasource.SmartDataSource接口是 javax.sql.DataSource接口的一个扩展,用一种未包装的形式返回Jdbc的连接。实现该接口的类可以查询Connection在完成操作之后是否应该关闭。在Srping和DataSourceUitls和JdbcTemplate中会自动执行这样的检查。
总结
DataSourceUitls是一个强大的工具辅助类,不仅仅是提供了Connection的获取、释放和关闭,其实还提供了为Connection提供Spring事务的支持。a
DataUtils对Connection的获取、释放和关闭的操作学习的更多相关文章
- 通常每个套接字地址(协议/网络地址/端口)只允许使用一次。 数据库连接不释放测试 连接池 释放连接 关闭连接 有关 redis-py 连接池会导致服务器产生大量 CLOSE_WAIT 的再讨论以及一个解决方案
import pymysqlfrom redis import Redisimport time h, pt, u, p, db = '192.168.2.210', 3306, 'root', 'n ...
- 多个iframe中根据src获取特定iframe并执行操作
多个iframe中根据src获取特定iframe并执行操作 前言:在项目中做一个批量编辑工单时需要在一大堆的iframe中的某一个iframe里边再用模态框的形式显示编辑区域,然后再在模态框里边加入i ...
- 【Python】[技术博客] 一些使用Python编写获取手机App日志的操作
一些使用Python编写获取手机App日志的操作 如何获取手机当前打开的App的包名 如何获取当前App进程的PID 如何查看当前App的日志 如何将日志保存到文件 如何关闭进程 如何不显示命令行窗口 ...
- Js获取当前日期时间及其它操作
Js获取当前日期时间及其它操作var myDate = new Date();myDate.getYear(); //获取当前年份(2位)myDate.getFullYear(); //获取完整的年份 ...
- C#获取窗口,模拟按键操作
C#获取窗口,模拟按键操作,实现计算器模拟操作.首先引用. using System.Runtime.InteropServices; 使用DllImport引入两个函数: // Get a hand ...
- jQuery获取checkbox选中项等操作及注意事项
jQuery获取checkbox选中项等操作及注意事项 今天在做一个项目功能时需要显示checkbox选项来让用户进行选择,由于前端不是很熟练,所以做了一个简单的Demo,其中遇到一些小问题,特记录下 ...
- Linux 开启和关闭 Ping 操作
Linux 默认是开启 ping 操作的,通过以下两种方式可以开启和关闭 ping 操作 . 1.修改内核参数 通过内核参数设置也有两种方式,一种是临时修改,一种是永久修改. 1.1 临时设置 PIN ...
- 【转】Js获取当前日期时间及其它操作
Js获取当前日期时间及其它操作 原文地址:http://www.cnblogs.com/carekee/articles/1678041.html var myDate = new Date();my ...
- [转]Js获取当前日期时间及其它操作
转载自:http://www.cnblogs.com/carekee/articles/1678041.html Js获取当前日期时间及其它操作 var myDate = new Date();myD ...
随机推荐
- resin4.0.25 安装配置 及结合eclipse开发
resin4.0.25 安装配置 及结合eclipse开发 本文大部分内容是对官网的翻译,及自己配置后的一些体会. 一. 基于win ,resin基本安装1,安装jdk1.6或更高版本2,配置环境 ...
- Spring Boot初识(3)- Spring Boot整合Swagger
一.本文介绍 如果Web项目是完全前后端分离的话(我认为现在完全前后端分离已经是趋势了)一般前端和后端交互都是通过接口的,对接口入参和出参描述的文档就是Mock文档.随着接口数量的增多和参数的个数增加 ...
- jqGrid 翻页
比如查出来有9条数据,表格第一页显示5条,第二页显示4条 第一次查询,后台返回9条数据,但是只显示第一页的5条, 当点击下一页,会再去数据库查询,只返回第二页的4条数据, 这时候再点击回到上一页,返回 ...
- Spring之Bean的注入
Bean的配置中介绍的是Bean声明问题,在哪声明怎么声明的问题.Bean的注入是怎么实例化,怎么注入的问题.Bean注入的方式有两种,一种是在XML中配置,另一种则是使用注解的方式注入. 一.XML ...
- S3C2440 DMA 驱动示例
将 DMA 抽象为一个字符设备,在初始化函数中调用 void *dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t * ...
- C++ 重载运算符简单举例
我们可以重定义或重载大部分 C++ 内置的运算符.这样,就能使用自定义类型的运算符. 重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的.与其他函数一 ...
- js串口通信 调用MSCOMM32控件 链接电子秤(完整版实现方案)
硬件环境:RS232转USB串口线*1 电子秤*1(本人采用G&G E600Y-C型号称重仪) 电子秤原装RS232数据线*1 计算机*1 软件环境:RS232转USB串口线驱动(这个可以在串 ...
- C# if---else---练习题整理
if else 语句是到今天为止学习的第一个完整的语句,把有意思的练习题整理下来开一下脑洞!!! 练习一简单的人工智能 1 static void Main(string[] args) ...
- (整理)Sublime Text 3 安装、破解、安装Package Control、汉化、添加到右键菜单、代码格式化、禁止更新
Sublime Text 3好用,但是每次安装到最后用着顺手,得在网上找半天安装.破解.安装Package Control.汉化.添加到右键菜单.代码格式化等等的教程,今天有空给自己整理一下吧. 一. ...
- [日常] C语言中指针变量
CPU 访问内存时需要的是地址,而不是变量名和函数名!变量名和函数名只是地址的一种助记符,当源文件被编译和链接成可执行程序后,它们都会被替换成地址.编译和链接过程的一项重要任务就是找到这些名称所对应的 ...