一,现在已经返回了结果集,接下来是对返回数据的分析
ResultSet.next()只不过是对rowData集合的操作
public synchronized boolean next() throws SQLException {
checkClosed();
if (this.onInsertRow) {
this.onInsertRow = false;
}
if (this.doingUpdates) {
this.doingUpdates = false;
}
boolean b;
if (!reallyResult()) {
throw SQLError.createSQLException(
Messages
.getString("ResultSet.ResultSet_is_from_UPDATE._No_Data_115"),
SQLError.SQL_STATE_GENERAL_ERROR, getExceptionInterceptor()); //$NON-NLS-1$
}
if (this.thisRow != null) {
this.thisRow.closeOpenStreams();
}
if (this.rowData.size() == 0) {
b = false;
} else {
//下一行数据
this.thisRow = this.rowData.next();
if (this.thisRow == null) {
b = false;
} else {
clearWarnings();
b = true;
}
}
setRowPositionValidity();
return b;
}
以ResultSet.getByte("")获取数据为例
//findColumn()方法,会找到相应的索引位置
public byte[] getBytes(String columnName) throws SQLException {
return getBytes(findColumn(columnName));
}
public byte getByte(int columnIndex) throws SQLException {
if (!this.isBinaryEncoded) {
//先通getString获取
String stringVal = getString(columnIndex);
if (this.wasNullFlag || (stringVal == null)) {
return 0;
}
return getByteFromString(stringVal, columnIndex);
}
return getNativeByte(columnIndex);
}
//===========
//通过索引位置获取字符串值
public String getString(int columnIndex) throws SQLException {
String stringVal = getStringInternal(columnIndex, true);
if (this.padCharsWithSpace && stringVal != null) {
Field f = this.fields[columnIndex - 1];
if (f.getMysqlType() == MysqlDefs.FIELD_TYPE_STRING ) {
int fieldLength = (int)f.getLength() /* safe, bytes in a CHAR <= 1024 */ /
f.getMaxBytesPerCharacter(); /* safe, this will never be 0 */
int currentLength = stringVal.length();
if (currentLength < fieldLength) {
StringBuffer paddedBuf = new StringBuffer(fieldLength);
paddedBuf.append(stringVal);
int difference = fieldLength - currentLength;
paddedBuf.append(EMPTY_SPACE, 0, difference);
stringVal = paddedBuf.toString();
}
}
}
return stringVal;
}
//==================
protected String getStringInternal(int columnIndex, boolean checkDateTypes)
throws SQLException {
if (!this.isBinaryEncoded) {
checkRowPos();
checkColumnBounds(columnIndex);
if (this.fields == null) {
throw SQLError.createSQLException(
Messages
.getString("ResultSet.Query_generated_no_fields_for_ResultSet_99"), //$NON-NLS-1$
SQLError.SQL_STATE_INVALID_COLUMN_NUMBER, getExceptionInterceptor());
}
// JDBC is 1-based, Java is not !?
int internalColumnIndex = columnIndex - 1;
if (this.thisRow.isNull(internalColumnIndex)) {
this.wasNullFlag = true;
return null;
}
this.wasNullFlag = false;
//获取到相应的字段属性类
Field metadata = this.fields[internalColumnIndex];
String stringVal = null;
if (metadata.getMysqlType() == MysqlDefs.FIELD_TYPE_BIT) {
if (metadata.isSingleBit()) {
byte[] value = this.thisRow.getColumnValue(internalColumnIndex);
if (value.length == 0) {
return String.valueOf(convertToZeroWithEmptyCheck());
}
return String.valueOf(value[0]);
}
return String.valueOf(getNumericRepresentationOfSQLBitType(columnIndex));
}
String encoding = metadata.getCharacterSet();
//在根据next()操作时指定的thisRow中获取相应的数据(BufferRow)
stringVal = this.thisRow.getString(internalColumnIndex, encoding, this.connection);
//
// Special handling for YEAR type from mysql, some people
// want it as a DATE, others want to treat it as a SHORT
//
if (metadata.getMysqlType() == MysqlDefs.FIELD_TYPE_YEAR) {
if (!this.connection.getYearIsDateType()) {
return stringVal;
}
Date dt = getDateFromString(stringVal, columnIndex, null);
if (dt == null) {
this.wasNullFlag = true;
return null;
}
this.wasNullFlag = false;
return dt.toString();
}
// Handles timezone conversion and zero-date behavior
if (checkDateTypes && !this.connection.getNoDatetimeStringSync()) {
//所获取到的String值,根据metadata中的类型再进行相应的转换
switch (metadata.getSQLType()) {
case Types.TIME:
Time tm = getTimeFromString(stringVal, null, columnIndex,
this.getDefaultTimeZone(), false);
if (tm == null) {
this.wasNullFlag = true;
return null;
}
this.wasNullFlag = false;
return tm.toString();
case Types.DATE:
Date dt = getDateFromString(stringVal, columnIndex, null);
if (dt == null) {
this.wasNullFlag = true;
return null;
}
this.wasNullFlag = false;
return dt.toString();
case Types.TIMESTAMP:
Timestamp ts = getTimestampFromString(columnIndex,
null, stringVal, this.getDefaultTimeZone(), false);
if (ts == null) {
this.wasNullFlag = true;
return null;
}
this.wasNullFlag = false;
return ts.toString();
default:
break;
}
}
return stringVal;
}
return getNativeString(columnIndex);
}
//
//BufferRow继承了ResultSetRow下获取相应的值
public String getString(int columnIndex, String encoding, MySQLConnection conn)
throws SQLException {
if (this.isBinaryEncoded) {
if (isNull(columnIndex)) {
return null;
}
}
//指针指向到相应的列
findAndSeekToOffset(columnIndex);
long length = this.rowFromServer.readFieldLength();
if (length == Buffer.NULL_LENGTH) {
return null;
}
if (length == 0) {
return "";
}
// TODO: I don't like this, would like to push functionality back
// to the buffer class somehow
int offset = this.rowFromServer.getPosition();
//获取到值,后对string进行相应的转换
return getString(encoding, conn, this.rowFromServer.getByteBuffer(),
offset, (int) length);
}
//BufferRow
protected String getString(String encoding, MySQLConnection conn,
byte[] value, int offset, int length) throws SQLException {
String stringVal = null;
if ((conn != null) && conn.getUseUnicode()) {
try {
if (encoding == null) {
stringVal = StringUtils.toString(value);
} else {
SingleByteCharsetConverter converter = conn
.getCharsetConverter(encoding);
if (converter != null) {
//对编码的一些转换
stringVal = converter.toString(value, offset, length);
} else {
//或者常用类中的转换
stringVal = StringUtils.toString(value, offset, length, encoding);
}
}
} catch (java.io.UnsupportedEncodingException E) {
throw SQLError
.createSQLException(
Messages
.getString("ResultSet.Unsupported_character_encoding____101") //$NON-NLS-1$
+ encoding + "'.", "0S100", this.exceptionInterceptor);
}
} else {
stringVal = StringUtils.toAsciiString(value, offset, length);
}
return stringVal;
}