日期:2014-05-16  浏览次数:20272 次

JDBC学习之-Connection(一)

JDBC是作为连接数据库的渠道之一,封装了一些与数据库交互的接口。看了一些源码,现在就来探寻一下JDBC的原理。

JDK中给了几个接口比如说Connection,Statement,ResultSet。这些都是在用JDBC中比较常用的接口,这些接口定义了与数据库的交互规则。具体的实现都由具体的类库或者厂商实现。目前比较常用的数据库有Mysql,Oracle,Sql Server。这些具体的数据库所实现的通信协议都会有差异。而JDBC就需要屏蔽这些差异,对外提供一个统一而且简单的接口。对于使用者而言,他只要关心如何创立连接,而不需要关心里面的具体通信协议。如果看源码就会知道其内部都是用TCP/IP通信协议进行通信,如果自己要实现一个JDBC这样的API的话则需要了解具体的数据库的通信协议。但是这些都不是程序员需要关心的事情。他们更加关心偏业务的事情。比如我一条SQL语句简单的提交就可以实现对数据库的增删改查,如何用已有的接口实现事务的回滚。

好了,废话不多讲。先看看一个重量级的接口Connection。顾名思议,连接,和数据库交互最基本的就是要和数据库建立连接。这个对象并非我们简单的new出来,而是由一个叫做DriverManager的管理者给我们创建好的。先上传一张Connection创建的时序图,时序图中完整的描述出一个Connection的创建。


    

Connection conn = DriverManager.getConnection(url,user,password);
面一行代码就是一条非常常用的建立连接的方法。这里问题就出来了,我们拿到的是Connection接口,而具体的Connection实现类又由谁来创建呢?

	static {
		try {
			java.sql.DriverManager.registerDriver(new Driver());
		} catch (SQLException E) {
			throw new RuntimeException("Can't register driver!");
		}
	}
上面这段代码是com.mysql.jdbc.Driver里面一段静态注册的代码。这段代码的意图很明显,在DriverManager里面注册一个具体的Driver类(PS:里面的new Driver()正是com.mysql.jdbc.Driver)。

	for (int i = 0; i < drivers.size(); i++) {
	    DriverInfo di = (DriverInfo)drivers.elementAt(i);
      
	    // If the caller does not have permission to load the driver then 
	    // skip it.
	    if ( getCallerClass(callerCL, di.driverClassName ) != di.driverClass ) {
		println("    skipping: " + di);
		continue;
	    }
	    try {
		println("    trying " + di);
		Connection result = di.driver.connect(url, info);
		if (result != null) {
		    // Success!
		    println("getConnection returning " + di);
		    return (result);
		}
	    } catch (SQLException ex) {
		if (reason == null) {
		    reason = ex;
		}
	    }
	}

上面这段代码DriverManager里面获取Connection的一个片断,其他的都不用关心只要关心一行代码:Connection result = di.driver.connect(url, info);上面我已经说过了,这里di.driver就是具体的Driver类。

我们再看看NonRegisteringDriver(Driver正是继承于它)这个类的方法。其他的也不是现在需要关心的,里面Connection newConn = com.mysql.jdbc.ConnectionImpl.getInstance(host(props), port(props), props, database(props), url);正是核心所在,当然ConnectionImpl里面做了很多操作,比如说Socket之类的等等。有兴趣的可以看源码。

	public java.sql.Connection connect(String url, Properties info)
			throws SQLException {
		if (url != null) {
			if (StringUtils.startsWithIgnoreCase(url, LOADBALANCE_URL_PREFIX)) {
				return connectLoadBalanced(url, info);
			} else if (StringUtils.startsWithIgnoreCase(url,
					REPLICATION_URL_PREFIX)) {
				return connectReplicationConnection(url, info);
			}
		}

		Properties props = null;

		if ((props = parseURL(url, info)) == null) {
			return null;
		}

		try {
			Connection newConn = com.mysql.jdbc.ConnectionImpl.getInstance(
					host(props), port(props), props, database(props), url);//这里终于可以看到具体的Connection实现类。

			return newConn;
		} catch (SQLException sqlEx) {
			// Don't wrap SQLExceptions, throw
			// them un-changed.
			throw sqlEx;
		} catch (Exception ex) {
			SQLException sq