`
zddava
  • 浏览: 243038 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Derby源代码分析 -- JDBC实现(一)

阅读更多
谈起JDBC的实现,还是从获取Connection开始吧。

下面这句就是一般的获取Connection的代码了,

DriverManager.getConnection(url, "username", "password");


当每个Driver初始化的时候,都会在DriverManager中注册下自己,就是调用这个registerDriver(java.sql.Driver driver)静态方法,然后当想获得Connnection的时候DriverManager就可以通过注册的驱动来从特定的数据库获得了。如果有兴趣可以看一下JDK中DriverManager的#getConnection()的实现,这里就不再列出代码了。而这里需要说明的是在#gertConnection()方法中会调用到先前注册的Driver的#connect(String url, Properties info)方法,其中info里保存了用户名和密码。下面就从这里开始分析吧。

1. 网络服务器方式

网络服务器方式对应的Driver是org.apache.derby.jdbc.ClientDriver,它的#connect()方法如下所示:


	public java.sql.Connection connect(String url, java.util.Properties properties) throws java.sql.SQLException {
		org.apache.derby.client.net.NetConnection conn;
		try {
			if (exceptionsOnLoadDriver__ != null) {
				throw exceptionsOnLoadDriver__;
			}

			if (properties == null) {
				properties = new java.util.Properties();
			}

			/* URL的格式类似于jdbc:derby://127.0.0.1:1527/database;create=true这种 */

			/* URL格式分析 */
			java.util.StringTokenizer urlTokenizer = new java.util.StringTokenizer(url, "/:= \t\n\r\f", true);

			int protocol = tokenizeProtocol(url, urlTokenizer);
			if (protocol == 0) {// 错误的URL前缀
				return null;
			}

			String slashOrNull = null;
			if (protocol == DERBY_REMOTE_PROTOCOL) {// 如果是网络方式的URL
				try {
					slashOrNull = urlTokenizer.nextToken(":/");
				} catch (java.util.NoSuchElementException e) {
					throw new SqlException(null, new ClientMessageId(SQLState.MALFORMED_URL), url, e);
				}
			}
			/* 地址 */
			String server = tokenizeServerName(urlTokenizer, url); // "/server"
			/* 端口 */
			int port = tokenizeOptionalPortNumber(urlTokenizer, url); // "[:port]/"
			if (port == 0) {// port没有的话就设为默认的1527
				port = ClientDataSource.propertyDefault_portNumber;
			}

			/* 数据库名 */
			String database = tokenizeDatabase(urlTokenizer, url); // "database"
			/* 这里还要加上一些URL中的参数进去,比如create=true这种 */
			java.util.Properties augmentedProperties = tokenizeURLProperties(url, properties);
			database = appendDatabaseAttributes(database, augmentedProperties);

			int traceLevel;
			try {
				traceLevel = ClientDataSource.getTraceLevel(augmentedProperties);
			} catch (java.lang.NumberFormatException e) {
				throw new SqlException(null, new ClientMessageId(SQLState.TRACELEVEL_FORMAT_INVALID), e);
			}

			org.apache.derby.client.am.LogWriter dncLogWriter = ClientDataSource.computeDncLogWriterForNewConnection(
					java.sql.DriverManager.getLogWriter(), ClientDataSource.getTraceDirectory(augmentedProperties),
					ClientDataSource.getTraceFile(augmentedProperties), ClientDataSource
							.getTraceFileAppend(augmentedProperties), traceLevel, "_driver", traceFileSuffixIndex_++);

			/* 这步是获得连接的过程,下面要重点看一下 */
			conn = (org.apache.derby.client.net.NetConnection) getFactory().newNetConnection(
					(org.apache.derby.client.net.NetLogWriter) dncLogWriter, java.sql.DriverManager.getLoginTimeout(),
					server, port, database, augmentedProperties);
		} catch (SqlException se) {
			throw se.getSQLException();
		}

		if (conn.isConnectionNull())
			return null;

		return conn;
	}



这里的#getFactory()方法就是首先要关注的地方之一,

	public static ClientJDBCObjectFactory getFactory() {
		if (factoryObject != null)
			return factoryObject;
		if (Configuration.supportsJDBC40()) {// 由于我的JDK是1.6的,只关注JDBC4.0的部分
			factoryObject = createJDBC40FactoryImpl();
		} else {
			factoryObject = createDefaultFactoryImpl();
		}
		return factoryObject;
	}

	private static ClientJDBCObjectFactory createJDBC40FactoryImpl() {
		final String factoryName = "org.apache.derby.client.net.ClientJDBCObjectFactoryImpl40";
		try {
			return (ClientJDBCObjectFactory) Class.forName(factoryName).newInstance();
		} catch (ClassNotFoundException cnfe) {
			return createDefaultFactoryImpl();
		} catch (InstantiationException ie) {
			return createDefaultFactoryImpl();
		} catch (IllegalAccessException iae) {
			return createDefaultFactoryImpl();
		}
	}


通过这里获得了一个org.apache.derby.client.net.ClientJDBCObjectFactoryImpl40的实例,它就是用来最后获取Connection实例的,回到之前的#connect()方法,这里调用了ClientJDBCObjectFactory的#newNetConnection()去获得Connection实例,


	public org.apache.derby.client.am.Connection newNetConnection(org.apache.derby.client.am.LogWriter netLogWriter,
			String user, String password, org.apache.derby.jdbc.ClientBaseDataSource dataSource, int rmId,
			boolean isXAConn) throws SqlException {
		return (org.apache.derby.client.am.Connection) (new NetConnection40((NetLogWriter) netLogWriter, user,
				password, dataSource, rmId, isXAConn));
	}



这里可以看出,其实是实例化了一个NetConnection40的实例返回给调用端,也就是说以后进一步的讨论都可以从NetConnection40开始了。


2. 嵌入式方式

下面就要看看嵌入式方式了,JDBC4.0的嵌入式Driver是Driver40这个类,不过这个类并没有重写#connect()方法,可以沿着继承树向上,在它的父类InternalDriver中看到这个方法


	public Connection connect(String url, Properties info) throws SQLException {
		if (!acceptsURL(url)) {
			return null;
		}

		/* 如果内存过低,那么不要尝试获取连接,直接抛出异常 */
		if (EmbedConnection.memoryState.isLowMemory()) {
			throw EmbedConnection.NO_MEM;
		}

		/* 是否要提供一个默认链接,URL是"jdbc:default:connection" */
		boolean current = url.equals(Attribute.SQLJ_NESTED);

		if (current) {
			ConnectionContext connContext = getConnectionContext();
			if (connContext != null) {
				return connContext.getNestedConnection(false);

			}
			return null;
		}

		FormatableProperties finfo = null;

		try {
			/* 获得URL中的属性,还包括了用户名和密码 */
			finfo = getAttributes(url, info);
			info = null; // ensure we don't use this reference directly again.

			/* 如果参数中包括了"shutdown",那么是要通知服务器关闭的 */
			boolean shutdown = Boolean.valueOf(finfo.getProperty(Attribute.SHUTDOWN_ATTR)).booleanValue();

			if (shutdown) {// 关闭操作
				if (InternalDriver.getDatabaseName(url, finfo).length() == 0) {
					if (this.getAuthenticationService() == null)
						throw Util.generateCsSQLException(SQLState.LOGIN_FAILED, MessageService
								.getTextMessage(MessageId.AUTH_NO_SERVICE_FOR_SYSTEM));

					if (!this.getAuthenticationService().authenticate((String) null, finfo)) {
						throw Util.generateCsSQLException(SQLState.NET_CONNECT_AUTH_FAILED, MessageService
								.getTextMessage(MessageId.AUTH_INVALID));
					}

					Monitor.getMonitor().shutdown();

					throw Util.generateCsSQLException(SQLState.CLOUDSCAPE_SYSTEM_SHUTDOWN);
				}
			}

			/* 获得嵌入式方式的连接 */
			EmbedConnection conn = getNewEmbedConnection(url, finfo);

			if (conn.isClosed()) {
				return null;
			}

			return conn;
		} catch (OutOfMemoryError noMemory) {// 这个好像不能捕捉到吧??
			EmbedConnection.memoryState.setLowMemory();
			throw EmbedConnection.NO_MEM;
		} finally {
			if (finfo != null)
				finfo.clearDefaults();
		}
	}


这段代码还是很好理解的,后边的#getNewEmbedConnection()方法各个不同JDBC版本的Driver就不尽相同了,我们来看一下JDBC4.0的好了,就是在Driver4里定义的那个,

	protected EmbedConnection getNewEmbedConnection(String url, Properties info) throws SQLException {
		return new EmbedConnection40(this, url, info);
	}


非常简单,返回了一个EmbedConnection40作为Connection的实现。

至此,网络服务器方式和嵌入式方式的连接获取就都分析完了,对于JDBC4.0,分别是NetConnection40和EmbedConnection40类。
分享到:
评论

相关推荐

    各种数据库的jdbc(mysql,orcal ,derby,hive,postgresql,monetdb-jdbc)

    JDBC提供了一种统一的接口,使得开发者可以轻松地切换不同的数据库系统,提高了代码的可移植性。同时,它还支持连接池、数据源等高级特性,以提升性能和管理效率。在实际开发中,理解并熟练使用这些数据库的JDBC特性...

    db-derby-10.11.1.1-src.zip

    在"db-derby-10.11.1.1-src"中,包含了Derby数据库的主要源代码,开发者可以通过阅读源码来学习如何设计和实现一个数据库系统,包括查询解析、存储引擎、事务管理、锁机制等核心部分。此外,"db-derby-10.11.1.1-doc...

    db-derby-10.11.1.1-bin.zip

    Apache Derby,也被称为Java DB,是一款轻量级、开源的关系型数据库管理系统,完全用Java编写,遵循Apache软件基金会的开放源代码协议。这个名为"db-derby-10.11.1.1-bin.zip"的压缩包包含了Apache Derby 10.11.1.1...

    jdbc接连数据库:oracle/derby/mysql

    博客链接提到的"源码"可能是指查看或分析JDBC驱动的源代码,理解其内部工作原理,而"工具"可能是指使用一些辅助工具,如数据库管理工具(如SQL Developer或MySQL Workbench),或者开发工具(如IDEA的数据库插件)来...

    spring-jdbc-4.2.xsd.zip

    总之,`spring-jdbc-4.2.xsd`是Spring JDBC模块配置的核心,它为Spring JDBC的配置提供了一套规范,使得开发者可以清晰、有序地设置数据库连接、数据源、事务管理等相关属性,提高了代码的可读性和可维护性。...

    Swing+derby仿QQ聊天软件及源码

    开发者可以查看这些源代码,学习如何利用Swing组件构建用户界面,以及如何通过Derby进行数据存储和检索。源码通常包括了类文件、资源文件以及可能的配置文件。通过阅读源码,初学者可以了解实际项目中Swing和Derby的...

    JavaSwing+derby通讯录源码

    5. **src目录**: 源码文件通常存放在src目录下,包括所有Java源代码文件(以.java为扩展名)。这里的源码应该是实现通讯录功能的类,比如用于显示和管理联系人的控制器类,以及可能的模型类和视图类。开发者可能会...

    Apache Derby 10.10版手册集

    1. 开源:Apache Derby遵循Apache License 2.0协议,允许用户自由地使用和分发,并可以根据自己的需求对源代码进行修改。 2. 嵌入式模式:Derby可以作为应用程序的一部分嵌入到应用中去运行,无需单独的服务器进程。...

    Eclipse下Apache Derby开发

    在开发Derby应用时,JDT用于编写和管理Java源代码,创建JDBC客户端应用程序,这些应用程序将与Derby数据库进行交互。 DB2 plug-ins for Eclipse是IBM提供的扩展,它增强了Eclipse对多种数据库(包括Apache Derby)...

    Derby数据库ij工具的使用

    Apache Derby项目的目标是构建一个完全用 Java 编程语言编写的、易于使用却适合大多数应用程序的开放源码数据库。Derby 数据库符合许多数据库标准,例如 SQL-92 和 JDBC 3.0 版本,所以开始用 Derby 数据库系统开发...

    Derby 命令(转载)

    在标签"源码"提及的情况下,对于开发者来说,Apache Derby的源代码是开放的,这意味着你可以查看、学习甚至贡献代码到项目中。这为理解数据库内部工作原理,调试问题,或者定制特定需求提供了可能性。 至于"工具...

    derby辅助工具SQuirreL SQL Client的使用

    - **方法一:使用内置Derby插件**:Eclipse有内建的Derby支持,可以通过Window > Preferences > Database Development > Drivers添加Derby驱动,然后创建数据源。 - **方法二:通过Eclipse Marketplace安装插件**...

    derby,jtds,mysql,oracle,sql2000,sql2005的jdbc数据库驱动

    2. **jTDS**:jTDS是一个开放源代码的JDBC驱动,主要针对Microsoft SQL Server和Sybase Adaptive Server Anywhere。它实现了JDBC Type 4驱动,能直接与数据库服务器通过TCP/IP通信,提供高速、稳定的数据访问。 3. ...

    Derby使用ij工具操作数据库

    Derby是一款开源、轻量级的关系型数据库管理系统,由Apache软件基金会开发并维护。它被设计为嵌入式数据库,适合于Java应用...在实际项目中,结合源码分析和相关工具的使用,可以更深入地理解和优化Derby数据库的性能。

    JdbcDerby:通过jdbc与derby连接

    - `src`目录:Java源代码文件,包含上述示例中的类。 - `lib`目录(可选):可能包含Apache Derby的JDBC驱动库文件(如`derby.jar`)。 - `build.xml`或`pom.xml`:构建脚本,可能是Ant或Maven,用于编译和打包项目...

    简单的JDBC应用程序for_Java_DB

    本文详细介绍了如何构建一个简单的JDBC应用程序,通过具体的代码示例展示了如何使用JDBC API与Java DB进行交互,包括数据库的连接、SQL命令的执行以及资源的管理等关键步骤。这对于初学者来说是非常好的入门教程,有...

    MyEclipse Derby是什么.txt

    6. **开放源代码:**作为ASF的一个项目,Derby的源代码完全开放,这有助于开发者深入理解其内部机制,并根据自身需求进行定制和扩展。 #### 五、Derby的应用场景 由于其轻量级和易于集成的特点,Derby广泛应用于...

Global site tag (gtag.js) - Google Analytics