谈起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提供了一种统一的接口,使得开发者可以轻松地切换不同的数据库系统,提高了代码的可移植性。同时,它还支持连接池、数据源等高级特性,以提升性能和管理效率。在实际开发中,理解并熟练使用这些数据库的JDBC特性...
在"db-derby-10.11.1.1-src"中,包含了Derby数据库的主要源代码,开发者可以通过阅读源码来学习如何设计和实现一个数据库系统,包括查询解析、存储引擎、事务管理、锁机制等核心部分。此外,"db-derby-10.11.1.1-doc...
Apache Derby,也被称为Java DB,是一款轻量级、开源的关系型数据库管理系统,完全用Java编写,遵循Apache软件基金会的开放源代码协议。这个名为"db-derby-10.11.1.1-bin.zip"的压缩包包含了Apache Derby 10.11.1.1...
博客链接提到的"源码"可能是指查看或分析JDBC驱动的源代码,理解其内部工作原理,而"工具"可能是指使用一些辅助工具,如数据库管理工具(如SQL Developer或MySQL Workbench),或者开发工具(如IDEA的数据库插件)来...
总之,`spring-jdbc-4.2.xsd`是Spring JDBC模块配置的核心,它为Spring JDBC的配置提供了一套规范,使得开发者可以清晰、有序地设置数据库连接、数据源、事务管理等相关属性,提高了代码的可读性和可维护性。...
开发者可以查看这些源代码,学习如何利用Swing组件构建用户界面,以及如何通过Derby进行数据存储和检索。源码通常包括了类文件、资源文件以及可能的配置文件。通过阅读源码,初学者可以了解实际项目中Swing和Derby的...
5. **src目录**: 源码文件通常存放在src目录下,包括所有Java源代码文件(以.java为扩展名)。这里的源码应该是实现通讯录功能的类,比如用于显示和管理联系人的控制器类,以及可能的模型类和视图类。开发者可能会...
1. 开源:Apache Derby遵循Apache License 2.0协议,允许用户自由地使用和分发,并可以根据自己的需求对源代码进行修改。 2. 嵌入式模式:Derby可以作为应用程序的一部分嵌入到应用中去运行,无需单独的服务器进程。...
在开发Derby应用时,JDT用于编写和管理Java源代码,创建JDBC客户端应用程序,这些应用程序将与Derby数据库进行交互。 DB2 plug-ins for Eclipse是IBM提供的扩展,它增强了Eclipse对多种数据库(包括Apache Derby)...
Apache Derby项目的目标是构建一个完全用 Java 编程语言编写的、易于使用却适合大多数应用程序的开放源码数据库。Derby 数据库符合许多数据库标准,例如 SQL-92 和 JDBC 3.0 版本,所以开始用 Derby 数据库系统开发...
在标签"源码"提及的情况下,对于开发者来说,Apache Derby的源代码是开放的,这意味着你可以查看、学习甚至贡献代码到项目中。这为理解数据库内部工作原理,调试问题,或者定制特定需求提供了可能性。 至于"工具...
- **方法一:使用内置Derby插件**:Eclipse有内建的Derby支持,可以通过Window > Preferences > Database Development > Drivers添加Derby驱动,然后创建数据源。 - **方法二:通过Eclipse Marketplace安装插件**...
2. **jTDS**:jTDS是一个开放源代码的JDBC驱动,主要针对Microsoft SQL Server和Sybase Adaptive Server Anywhere。它实现了JDBC Type 4驱动,能直接与数据库服务器通过TCP/IP通信,提供高速、稳定的数据访问。 3. ...
Derby是一款开源、轻量级的关系型数据库管理系统,由Apache软件基金会开发并维护。它被设计为嵌入式数据库,适合于Java应用...在实际项目中,结合源码分析和相关工具的使用,可以更深入地理解和优化Derby数据库的性能。
- `src`目录:Java源代码文件,包含上述示例中的类。 - `lib`目录(可选):可能包含Apache Derby的JDBC驱动库文件(如`derby.jar`)。 - `build.xml`或`pom.xml`:构建脚本,可能是Ant或Maven,用于编译和打包项目...
本文详细介绍了如何构建一个简单的JDBC应用程序,通过具体的代码示例展示了如何使用JDBC API与Java DB进行交互,包括数据库的连接、SQL命令的执行以及资源的管理等关键步骤。这对于初学者来说是非常好的入门教程,有...
6. **开放源代码:**作为ASF的一个项目,Derby的源代码完全开放,这有助于开发者深入理解其内部机制,并根据自身需求进行定制和扩展。 #### 五、Derby的应用场景 由于其轻量级和易于集成的特点,Derby广泛应用于...