一,现在已经返回了结果集,接下来是对返回数据的分析
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; }