mysql jdbc驱动源码分析(获取Statement对象)

时间:2022-09-19 11:57:04

在前面的文章中我们分析了获取Connection 对象的代码,下面来看看获取Statement的源码:

ConnectionImpl类的createStatement() 方法获取Statement实例

 // 获取Statement对象,没有参数则使用默认的参数
public java.sql.Statement createStatement() throws SQLException {
// 这里的默认值就是在获得ResultSet的值后,不能滚动只能向后移动
return createStatement(DEFAULT_RESULT_SET_TYPE, DEFAULT_RESULT_SET_CONCURRENCY);
}


指定了该对象将生成具有给定类型和并发性的  ResultSet  对象。
  public java.sql.Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {        checkClosed();        // StatementImpl 的两个参数,一个是当前数据库的链接Connection 一个是当前用的数据库        StatementImpl stmt = new StatementImpl(getMultiHostSafeProxy(), this.database);        stmt.setResultSetType(resultSetType);        stmt.setResultSetConcurrency(resultSetConcurrency);        // 创建statement对象。        return stmt;    }
其中的 checkClosed() 方法就是检测Connection 链接有没有断开或关闭。


StatementImpl对象的获取从上面的代码中能看到是创建了一个<span style="font-family: Arial, Helvetica, sans-serif;">StatementImpl对象,</span><span style="font-family: Arial, Helvetica, sans-serif;">StatementImpl 构造函数源码如下:</span>

 /**
* Constructor for a Statement.
*
* @param c
* the Connection instantation that creates us
* @param catalog
* the database name in use when we were created
*
* @throws SQLException
* if an error occurs.
*/
public StatementImpl(MySQLConnection c, String catalog) throws SQLException {
//判断当前的链接有没有断开,如果为空或是断开了则抛出异常
if ((c == null) || c.isClosed()) {
throw SQLError.createSQLException(Messages.getString("Statement.0"), SQLError.SQL_STATE_CONNECTION_NOT_OPEN, null);
}

this.connection = c;
this.connectionId = this.connection.getId();
this.exceptionInterceptor = this.connection.getExceptionInterceptor();

this.currentCatalog = catalog;
this.pedantic = this.connection.getPedantic();
this.continueBatchOnError = this.connection.getContinueBatchOnError();
this.useLegacyDatetimeCode = this.connection.getUseLegacyDatetimeCode();
this.sendFractionalSeconds = this.connection.getSendFractionalSeconds();
this.doEscapeProcessing = this.connection.getEnableEscapeProcessing();

if (!this.connection.getDontTrackOpenResources()) {
this.connection.registerStatement(this);
}

this.maxFieldSize = this.connection.getMaxAllowedPacket();

int defaultFetchSize = this.connection.getDefaultFetchSize();
if (defaultFetchSize != 0) {
setFetchSize(defaultFetchSize);
}

if (this.connection.getUseUnicode()) {
this.charEncoding = this.connection.getEncoding();
this.charConverter = this.connection.getCharsetConverter(this.charEncoding);
}

boolean profiling = this.connection.getProfileSql() || this.connection.getUseUsageAdvisor() || this.connection.getLogSlowQueries();
if (this.connection.getAutoGenerateTestcaseScript() || profiling) {
this.statementId = statementCounter++;
}
if (profiling) {
this.pointOfOrigin = LogUtils.findCallingClassAndMethod(new Throwable());
this.profileSQL = this.connection.getProfileSql();
this.useUsageAdvisor = this.connection.getUseUsageAdvisor();
this.eventSink = ProfilerEventHandlerFactory.getInstance(this.connection);
}

int maxRowsConn = this.connection.getMaxRows();
if (maxRowsConn != -1) {
setMaxRows(maxRowsConn);
}

this.holdResultsOpenOverClose = this.connection.getHoldResultsOpenOverStatementClose();

this.version5013OrNewer = this.connection.versionMeetsMinimum(5, 0, 13);
}

到这里StatementImpl 对象就创建了,从构造函数我们可以看出,创建的过程就是设置了一些结果集展示的属性,如最大行数,字符编码等,不管设置什么属性他们都是依赖于当前的链接即Connectio 对象的,如果Connection为null 或者链接被关闭了则会报异常,即null 或者SQLError.SQL_STATE_CONNECTION_NOT_OPEN 所以,创建Statement对象的基础是要有Connection。还有如果有空闲的Statement我们可以重用,不用再次创建Statement对象。