六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 178|回复: 0

Derby源代码分析 -

[复制链接]

升级  98%

13

主题

13

主题

13

主题

童生

Rank: 1

积分
49
 楼主| 发表于 2013-1-14 23:04:46 | 显示全部楼层 |阅读模式
前面已经知道了对于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 {// rootConnectionapplicationConnection = rootConnection = this;// 对于JDBC4.0这里driver是Driver40类的实例factory = driver;// 这里初始化了TransactionResourceImpltr = new TransactionResourceImpl(driver, url, info);active = true;// 将ContextManager设为ContextService的当前ManagersetupContextStack();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.BasicDatabaseDatabase 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) {// 如果要创建一个新的databaseif (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的创建和启用等,这个构造方法其实还有很多需要研究的地方,下面来逐个的研究下。
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表