Derbyソースコード分析--JDBC実現(二)
JDBC 4.0に対して、java.sql.Connectionのネットワークサーバと組み込みの実現類は、それぞれNetConnection 40とEmbodConnection 40であることが分かりました。
次に、組み込み方式を例にとって、ResultSetの取得手順を説明します。
一般的な呼び出しプロセスは次のようになるべきです。
まずlccの実用化はEmbodStatitementの構造関数で行い、
そしてEmbodConnectionの構造関数を見てみます。これは比較的長いです。中間は一部を省略しました。
次に、組み込み方式を例にとって、ResultSetの取得手順を説明します。
一般的な呼び出しプロセスは次のようになるべきです。
Connection conn = DriverManager.getConnection(url, "username", "password");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select * from table");
while(rs.next()){
......
}
EmbodConnection 40の父親クラスorg.apache.dersby.impl.jdbc.EmbodConnectionで龚骱createStation()の実現を見つけることができます。 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);
}
次はnewEmbodStatiment()の実現を見て、JDBC 4.0に対してorg.apache.dersby.jdbc.Driver 40にこの方法の実現を探しに行きます。 public java.sql.Statement newEmbedStatement(EmbedConnection conn, boolean forMetaData, int resultSetType,
int resultSetConcurrency, int resultSetHoldability) {
return new EmbedStatement40(conn, forMetaData, resultSetType, resultSetConcurrency, resultSetHoldability);
}
Sttementの実現はorg.apache.dersby.impl.jdbc.EmbodStartement 40であることが分かります。その親タイプのEmbodStatementで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.dersby.iapi.sql.com.Language Connection Contect類の役割を見ます。まずlccの実用化はEmbodStatitementの構造関数で行い、
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;
}
この方法はEmbodConnectionで見つけられます。finalです。 public final LanguageConnectionContext getLanguageConnection() {
if (SanityManager.DEBUG)
SanityManager.ASSERT(!isClosed(), "connection is closed");
return getTR().getLcc();
}
ここではgetTR()の方法があります。finalのクラスTransactional ResourceImplに戻りました。この種類のJavaDocを見て、データベースとの接続、事務の文脈など、Langugenection Contectの実例を得ることができます。 LanguageConnectionContext getLcc() {
return lcc;
}
ここでlccの例は、startTransation方法で初期化され、 void startTransaction() throws StandardException, SQLException {
lcc = database.setupConnection(cm, username, drdaID, dbname);
}
ここには2つの場所がありますが、一つはいつからですか?もう一つはdatabaseが初期化されたのですか?この問題を知るためにはまずTransation Resource Implの構造関数を見て、そしてEmbodConnectionの構造関数を見てください。 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();
}
Transation Resource Implのコンストラクタでは、Contect Service(csf)とContect Manager(cm)を初期化しました。そしてEmbodConnectionの構造関数を見てみます。これは比較的長いです。中間は一部を省略しました。
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();
}
}
ここでは、EmbodConnectionのコンストラクタにおいて、Transaction Resource Impl(tr)の初期化、databaseの作成と有効化など、多くの研究が必要なところがあります。