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 ...
 
随机推荐
- Spring Boot + Spring Cloud 构建微服务系统(三):服务消费和负载(Feign)
			
Spring Cloud Feign Spring Cloud Feign是一套基于Netflix Feign实现的声明式服务调用客户端.它使得编写Web服务客户端变得更加简单.我们只需要通过创建接口 ...
 - [design-patterns]设计模式之一策略模式
			
设计模式 从今天开始开启设计模式专栏,我会系统的分析和总结每一个设计模式以及应用场景.那么首先,什么是设计模式呢,作为一个软件开发人员,程序人人都会写,但是写出一款逻辑清晰,扩展性强,可维护的程序就不 ...
 - Linux中重命名乱码文件
			
Linux下,如何将一个乱码的文件进行重命名 方法一: 命令格式:mv $(ls |egrep "[^a-zA-Z0-9.-]") tandao.tx [root@nb o]# l ...
 - CASE函数
			
-> 使用类似switch-case与if-else if -> 语法 •case [字段] • when 表达式 then 显示数据 • when 表达式 then 显示数据 ...
 - Spark集群的任务提交执行流程
			
本文转自:https://www.linuxidc.com/Linux/2018-02/150886.htm 一.Spark on Standalone 1.spark集群启动后,Worker向Mas ...
 - Java框架之Struts2(五)
			
本文主要介绍Struts2 文件上传.Struts2 多文件上传.文件下载.上传文件的过滤.输入校验.输入校验的流程. 一.Struts2 文件上传 步骤: 1) 页面 <form action ...
 - 【Java并发编程】20、DelayQueue实现订单的定时取消
			
当订单定时取消需要修改数据库订单状态,但是怎么确定订单什么时候应该改变状态,解决方案有下面两种: 第一种,写个定时器去每分钟扫描数据库,这样更新及时,但是如果数据库数据量大的话,会对数据库造成很大的压 ...
 - Apache SkyWalking的架构设计【译文】
			
Apache SkyWalking提供了一个功能强大并且很轻量级的后端.在此,将介绍为什么采用以下方式来设计它,以及它又是如何工作的. 架构图 对于APM而言,agent或SDKs仅是如何使用libs ...
 - 设置div背景透明的CSS样式
			
div背景透明样式: 样式代码: .alert{filter:alpha(opacity=100); /* IE */ -moz-opacity:1.0; /* Moz + FF */ opacity ...
 - CSS3属性-webkit-font-smoothing字体抗锯齿渲染
			
对字体进行抗锯齿渲染可以使字体看起来会更清晰舒服.在图标字体成为一种趋势的今天,抗锯齿渲染使用也越来越多. font-smoothing是非标准的CSS定义.它被列入标准规范的草案中,后由于某些原因从 ...