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

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

阅读更多
前面已经知道了对于JDBC4.0,java.sql.Connection的网络服务器和嵌入式的实现类分别为NetConnection40和EmbedConnection40。

下面就以就以嵌入式方式为例来说明下ResultSet的获取过程。

一个一般的调用过程应该是如下这样的,


	Connection conn = DriverManager.getConnection(url, "username", "password");
	Statement stmt = conn.createStatement();
	ResultSet rs = stmt.executeQuery("select * from table");
	while(rs.next()){
		......
	}



可以在EmbedConnection40的父类org.apache.derby.impl.jdbc.EmbedConnection找到#createStatement()的实现


	public final Statement createStatement() throws SQLException {
		return createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, connectionHoldAbility);
	}

	public final Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
			throws SQLException {
		checkIfClosed();
		/* 这里的factory究竟是哪个类的实例可以看一下前面Connection获取的部分,对于JDBC4.0就是Driver40的实例 */
		return factory.newEmbedStatement(this, false, setResultSetType(resultSetType), resultSetConcurrency,
				resultSetHoldability);
	}



下面要看一下newEmbedStatement()的实现,对于JDBC4.0,要去org.apache.derby.jdbc.Driver40找这个方法的实现,


	public java.sql.Statement newEmbedStatement(EmbedConnection conn, boolean forMetaData, int resultSetType,
			int resultSetConcurrency, int resultSetHoldability) {
		return new EmbedStatement40(conn, forMetaData, resultSetType, resultSetConcurrency, resultSetHoldability);
	}



这里可以看到Statement的实现是org.apache.derby.impl.jdbc.EmbedStatement40。在它的父类EmbedStatement中定义了executeQuery()方法,


	public java.sql.ResultSet executeQuery(String sql) throws SQLException {
		execute(sql, true, false, Statement.NO_GENERATED_KEYS, null, null);

		if (SanityManager.DEBUG) {
			if (results == null)
				SanityManager.THROWASSERT("no results returned on executeQuery()");
		}

		return results;
	}

	private boolean execute(String sql, boolean executeQuery, boolean executeUpdate, int autoGeneratedKeys,
			int[] columnIndexes, String[] columnNames) throws SQLException {
		synchronized (getConnectionSynchronization()) {

			checkExecStatus();
			if (sql == null) {
				throw newSQLException(SQLState.NULL_SQL_TEXT);
			}
			checkIfInMiddleOfBatch();

			/* 关闭与这个Statement关联的ResultSet */
			clearResultSets();

			setupContextStack();

			SQLText = sql;

			try {
				/* 获取Activation对象 */
				Activation activation;
				try {
					PreparedStatement preparedStatement = lcc.prepareInternalStatement(lcc.getDefaultSchema(), sql,
							resultSetConcurrency == java.sql.ResultSet.CONCUR_READ_ONLY, false);
					activation = preparedStatement.getActivation(lcc,
							resultSetType == java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE);
					checkRequiresCallableStatement(activation);
				} catch (Throwable t) {
					throw handleException(t);
				}

				activation.setSingleExecution();

				if (autoGeneratedKeys == Statement.RETURN_GENERATED_KEYS)
					activation.setAutoGeneratedKeysResultsetInfo(columnIndexes, columnNames);

				/* 执行Statement */
				return executeStatement(activation, executeQuery, executeUpdate);
			} finally {
				restoreContextStack();
			}
		}
	}



这里要首先看一下lcc这个实例对应的org.apache.derby.iapi.sql.conn.LanguageConnectionContext类的作用。

首先lcc的实例化是在EmbedStatement的构造函数中进行的,


	public EmbedStatement(EmbedConnection connection, boolean forMetaData, int resultSetType, int resultSetConcurrency,
			int resultSetHoldability) {
		super(connection);
		this.forMetaData = forMetaData;
		this.resultSetType = resultSetType;
		this.resultSetConcurrency = resultSetConcurrency;
		this.resultSetHoldability = resultSetHoldability;

		/* 这里就是lcc的初始化了 */
		lcc = getEmbedConnection().getLanguageConnection();
		applicationConnection = getEmbedConnection().getApplicationConnection();
		applicationStatement = this;
	}



可以在EmbedConnection中找到这个方法#getLanguageConnection()方法,它是final的


	public final LanguageConnectionContext getLanguageConnection() {

		if (SanityManager.DEBUG)
			SanityManager.ASSERT(!isClosed(), "connection is closed");

		return getTR().getLcc();
	}



这里有一个getTR()方法,返回了一个final的类TransactionResourceImpl,看这个类的JavaDoc,它负责的事情还是很多的,比如与数据库的连接,事务的上下文等,在TransactionResourceImpl中可以通过getLcc()方法得到LanguageConnectionContext实例。


	LanguageConnectionContext getLcc() {
		return lcc;
	}



这里lcc实例是在startTransaction()方法中初始化的,


	void startTransaction() throws StandardException, SQLException {
		lcc = database.setupConnection(cm, username, drdaID, dbname);
	}



这里有2个地方还不清楚,一个是#startTransaction()方法是何时调用的,另外一个是database是什么时候初始化的,要了解这个问题首先要看一下TransactionResourceImpl的构造函数,然后还要看一下EmbedConnection的构造函数


	TransactionResourceImpl(InternalDriver driver, String url, Properties info) throws SQLException {
		/* 对于JDBC4.0这里driver是Driver40类的实例 */
		this.driver = driver;

		/* csf是一个org.apache.derby.iapi.services.context.ContextService的实例 */
		/* ContextService是一个访问上下文的工具方法类 */
		csf = driver.getContextServiceFactory();

		dbname = InternalDriver.getDatabaseName(url, info);
		this.url = url;

		username = IdUtil.getUserNameFromURLProps(info);

		drdaID = info.getProperty(Attribute.DRDAID_ATTR, null);

		// ContextManager对象,这里ContextManager还要push一个org.apache.derby.iapi.services.context.SystemContext到ContextManager中
		cm = csf.newContextManager();
	}



在TransactionResourceImpl的构造函数里,对ContextService(csf)和ContextManager(cm)进行了初始化。

然后看一下EmbedConnection的构造函数,这个比较长,中间略过了一部分。


	public EmbedConnection(InternalDriver driver, String url, Properties info) throws SQLException {
		// rootConnection
		applicationConnection = rootConnection = this;

		// 对于JDBC4.0这里driver是Driver40类的实例
		factory = driver;

		// 这里初始化了TransactionResourceImpl
		tr = new TransactionResourceImpl(driver, url, info);

		active = true;

		// 将ContextManager设为ContextService的当前Manager
		setupContextStack();

		try {
			// 初始化一个EmbedConnectionContext实例,并且push这个Context到ContextManager中
			EmbedConnectionContext context = pushConnectionContext(tr.getContextManager());

			boolean shutdown = Boolean.valueOf(info.getProperty(Attribute.SHUTDOWN_ATTR)).booleanValue();

			// 查看database模块是否启动了,在modules.properties中定义的是org.apache.derby.impl.db.BasicDatabase
			Database database = (Database) Monitor.findService(Property.DATABASE_MODULE, tr.getDBName());

			// 查看是否用户想创建一个新的数据库
			boolean createBoot = createBoot(info);

			boolean isTwoPhaseEncryptionBoot = (!createBoot && isEncryptionBoot(info));
			boolean isTwoPhaseUpgradeBoot = (!createBoot && isHardUpgradeBoot(info));
			/* 如果数据库连接的属性中包括"startSlave",那么是使用了Replication slave模式 */
			/* 这部分关于Master-Slave的内容我也没有研究 */
			boolean isStartSlaveBoot = isStartReplicationSlaveBoot(info);

			boolean slaveDBAlreadyBooted = false;

			boolean isFailoverMasterBoot = false;
			boolean isFailoverSlaveBoot = false;

			......
			......

			if (database != null) {// database已经启动了
				tr.setDatabase(database);
				isTwoPhaseEncryptionBoot = false;
				isTwoPhaseUpgradeBoot = false;
			} else if (!shutdown) {
				if (isTwoPhaseEncryptionBoot || isTwoPhaseUpgradeBoot) {
					savedInfo = info;
					info = removePhaseTwoProps((Properties) info.clone());
				}

				if (!bootDatabase(info, isTwoPhaseUpgradeBoot)) {
					tr.clearContextInError();
					setInactive();
					return;
				}
			}

			if (createBoot && !shutdown) {// 如果要创建一个新的database
				if (tr.getDatabase() != null) {
					// database已经存在
					addWarning(SQLWarningFactory.newSQLWarning(SQLState.DATABASE_EXISTS, getDBName()));
				} else {
					checkUserCredentials(null, info);
					// 创建一个新的
					database = createDatabase(tr.getDBName(), info);
					/*这里将database设定到了TransactionResourceImpl*/
					tr.setDatabase(database);
				}
			}

			if (tr.getDatabase() == null) {// database没有启动
				handleDBNotFound();
			}

			try {
				//看看这个用户是否合法
				checkUserCredentials(tr.getDBName(), info);
			} catch (SQLException sqle) {
				if (isStartSlaveBoot && !slaveDBAlreadyBooted) {
					tr.startTransaction();
					handleException(tr.shutdownDatabaseException());
				}
				throw sqle;
			}

			// 这里就是lcc实例的获取了,这个方法后边还要仔细看
			tr.startTransaction();			

			......
			......

		} catch (OutOfMemoryError noMemory) {
			restoreContextStack();
			tr.lcc = null;
			tr.cm = null;

			memoryState.setLowMemory();

			throw NO_MEM;
		} catch (Throwable t) {
			if (t instanceof StandardException) {
				StandardException se = (StandardException) t;
				if (se.getSeverity() < ExceptionSeverity.SESSION_SEVERITY)
					se.setSeverity(ExceptionSeverity.SESSION_SEVERITY);
			}
			tr.cleanupOnError(t);
			throw handleException(t);
		} finally {
			restoreContextStack();
		}
	}



这里,在EmbedConnection的构造函数中其实已经完成了很多的工作,比如TransactionResourceImpl(tr)的初始化,database的创建和启用等,这个构造方法其实还有很多需要研究的地方,下面来逐个的研究下。
分享到:
评论

相关推荐

    各种数据库的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.zip" 是Apache Derby的10.11.1.1版本的源代码包,对于开发者来说,这是一个宝贵的资源,可以深入了解Derby的内部工作原理和实现细节。 Apache Derby的核心特性包括: 1. **完全用Java编写...

    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的配置提供了一套规范,使得开发者可以清晰、有序地设置数据库连接、数据源、事务管理等相关属性,提高了代码的可读性和可维护性。...

    Eclipse下Apache Derby开发

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

    derby辅助工具SQuirreL SQL Client的使用

    - **方法一:使用内置Derby插件**:Eclipse有内建的Derby支持,可以通过Window &gt; Preferences &gt; Database Development &gt; 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. ...

    源代码检查工具SONAR使用经验

    ### 源代码检查工具SONAR使用经验 #### Sonar概述 Sonar作为一个代码质量管理的开放平台,通过灵活的插件机制集成了多种测试工具、代码分析工具以及持续集成工具。与传统持续集成工具(如Hudson/Jenkins)相比,...

    Derby 命令(转载)

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

    Apache Derby 10.10版手册集

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

    JdbcDerby:通过jdbc与derby连接

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

    apache-hive-1.2.2-src:蜂巢源代码学习-apache source code

    在深入学习`apache-hive-1.2.2-src`源代码之前,我们首先需要了解Hive的基本概念和工作流程。 Hive的核心组件包括: 1. **元数据存储**:Hive存储关于表、列、分区等元数据,通常在MySQL或Derby数据库中。 2. **...

    MyEclipse Derby是什么.txt

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

    销售信息管理系统v0.3带源代码.zip

    源代码的提供意味着用户可以查看、学习甚至修改系统的内部实现,以适应特定需求或进行二次开发。 Swing是Java的一个图形用户界面(GUI)工具包,它是Java Foundation Classes (JFC)的一部分,用于构建桌面应用。...

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

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

    JavaSwing+derby通讯录源码

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

    oracle jdbc mysql 等数据连接所有的配置

    在Java应用程序中通过JDBC(Java Database Connectivity)连接到Oracle数据库时,主要使用以下代码: ```java Class.forName("oracle.jdbc.driver.OracleDriver"); Connection con = DriverManager.getConnection(...

    常用的JDBC驱动名字

    1. **基本JDBC-ODBC桥接驱动**:这是一种基于ODBC的驱动,它不是纯Java实现的。 2. **部分Java驱动**:这种驱动需要本地代码与Java交互,提供了一些Java功能,但仍依赖于ODBC。 3. **网络协议纯Java驱动**:这类驱动...

Global site tag (gtag.js) - Google Analytics