Руководство по JDBC v.1
Предыдущий | Содержание | Следующий
5 - ResultSet (набор данных)
5.1 Обзор
ResultSet
содержит все строки, удовлетворяющие условиям в SQL-выражении и предоставляет
доступ к данным в этих строках посредством набора get-методов,
которые организуют доступ к колонкам текущей строки. Метод
ResultSet.next используется для перемещения к следующей строке
ResultSet, делая ее текущей.
Набор данных результата (result set) является таблицей с заголовками колонок
и соответствующих значений, возвращенных запросом. Например, если мы имеем
запрос SELECT a, b, c FROM Table1, то набор результата будет в
следующей форме:
a b c -------- --------- -------- 12345 Cupertino CA 83472 Redmond WA 83492 Boston MA
Следующий фрагмент кода демонстрирует выполнение
SQL-запроса, который возвращает коллекцию строк, в которой колонка 1 - это
int, колонка 2 - String и колонка 3 - массив байтов:
java.sql.Statement stmt = conn.createStatement();
ResultSet r = stmt.executeQuery("SELECT a, b, c FROM Table1");
while (r.next())
{
// Напечатать значения в текущей строке.
int i = r.getInt("a");
String s = r.getString("b");
float f = r.getFloat("c");
System.out.println("ROW = " + i + " " + s + " " + f);
}
5.1.1 Строки и курсоры
ResultSet содержит т.н. курсор, который указывает
на текущую строку данных. Каждый раз, когда выполняется метод next,
курсор перемещается на одну строку вниз. Изначально курсор спозиционирован перед
первой строкой, и первый вызов next премещает его на первую строку
(она становится текущей). С каждым успешным вызовом next курсор перемещается
вниз на одну строку, начиная с самой верхней в ResultSet.
Курсор сохраняется до тех пор, пока не закроется объект
ResultSet или его родительский объект Statement.
В SQL курсор для результирующей таблицы имеет имя. Если
БД поддерживает позиционированные обновления или позиционированные удаления, то
командам обновления или удаления можно передать в качестве параметра имя
курсора. Это имя может быть получено с помощью вызова
getCursorName.
Заметим, что не все СУБД поддерживают позиционированные
обновления или удаления. Чтобы узнать, поддерживает ли данное соединение эти
операции или нет, можно вызвать методы
DatabaseMetaData.supportsPositionedDelete и
supportsPositionedUpdate.
5.1.2 Колонки
МетодыgetXXX предоставляют доступ к значениям в колонках в текущей
строке. В пределах одной строки значения могут быть считаны в любом порядке, но
ради обеспечения большей совместимости рекомендуется считывать их подряд слева
направо и делать это только один раз.
Для указания колонки можно использовать либо ее имя, либо
ее номер. Например, если вторая колонка объекта ResultSet
rs называется "title" и хранит строковое значение, то извлечь его
можно одним из двух способов:
String s = rs.getString("title");
String s = rs.getString(2);Имейте ввиду, что колонки нумеруются слева направо,
начиная с 1. Имена колонок в вызове методов getXXX нечувствительны
к регистру букв.
Вариант с использованием имен колонок существует для того,
чтобы пользователь задавал методам getXXX те же имена колонок, что
он использует в запросе. Если выражение select не указывает имена
колонок (например "select * from table1" или в случаях, когда
колонка вычисляется) должны использоваться номера колонок. В этих случаях
пользователь не может знать наверняка имена колонок.
В нектороых случаях имена двух колонок могут совпадать.
Тогда при использовании имен колонок в методах getXXX возвращается
значение первой подходящей колонки. Таким образом, чтобы считать значение других
колонок с таким же именем, надо использовать индексы колонок. Кроме того,
использование индексов немного эффективнее.
Информацию о колонках в ResultSet можно
получить с помощтю вызова ResultSet.getMetaData. Возвращаемый
объект ResultSetMetaData содержит информацию о количестве, типах и
свойствах колонок объекта ResultSet.
Если известно имя колонки, но не ее индекс, то для поиска
номера колонки можно использовать метод findColumn.
5.1.3 Типы данных и их преобразование
МетодыgetXXX пытаются сконвертировать
низкоуровневые данные в типы данных языка Java. Например, метод если метод
getXXX - это getString и тип данных в БД -
VARCHAR, драйвер JDBC сконвертирует VARCHAR в объект
String. Возвращаемым из метода getString значением
будет Java-объект String.
Следующая таблица показывает, какие типы данных различные методы
getXXX могут считывать и какие JDBC-типы (SQL-типы) рекомендуются
для этих методов. Знак x означает, что метод getXXX
подходит к соответствующему типу данных; знак X означает
рекомендуемый метод getXXX для данного типа. Например, значение
LONGVARCHAR можно извлечь любым из методов getXXX
кроме getBytes и getBinaryStream, но рекомендуется
использовать методы getAsciiStream и getUnicodeStream.
Метод getObject возвращает любой тип данных как Object
и используется в тех случаях, когда соответствующий низкоуровневый тип данных
является специфичным для данной СУБД или когда приложению необходимо принять
любой тип данных.
Использование методов ResultSet.getXXX при доступе к
различным типам данных SQL.
"x" означает, что метод getXXX
может быть использован,
"X" означает, что соответствующий метод рекомендуется
использовать для этого типа данных.
| T I N Y I N T | S M A L L I N T | I N T E G E R | B I G N T | R E A L | F L O A T | D O U B L E | D E C I M A L | N U M E R I C | B I T | C H A R | V A R C H A R | L O N G V A R C H A R | B I N A R Y | V A R B I N A R Y | L O N G V A R B I N A R Y | D A T E | T I M E | T I M E S T A M P | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| getByte | X | x | x | x | x | x | x | x | x | x | x | x | x | ||||||
| getShort | x | X | x | x | x | x | x | x | x | x | x | x | x | ||||||
| getInt | x | x | X | x | x | x | x | x | x | x | x | x | x | ||||||
| getLong | x | x | x | X | x | x | x | x | x | x | x | x | x | ||||||
| getFloat | x | x | x | x | X | x | x | x | x | x | x | x | x | ||||||
| getDouble | x | x | x | x | x | X | X | x | x | x | x | x | x | ||||||
| getBigDecimal | x | x | x | x | x | x | x | X | X | x | x | x | x | ||||||
| getBoolean | x | x | x | x | x | x | x | x | x | X | x | x | x | ||||||
| getString | x | x | x | x | x | x | x | x | x | x | X | X | x | x | x | x | x | x | x |
| getBytes | X | X | x | ||||||||||||||||
| getDate | x | x | x | X | x | ||||||||||||||
| getTime | x | x | x | X | x | ||||||||||||||
| getTimestamp | x | x | x | x | X | ||||||||||||||
| getAsciiStream | x | x | X | x | x | x | |||||||||||||
| getUnicodeStream | x | x | X | x | x | x | |||||||||||||
| getBinaryStream | x | x | X | ||||||||||||||||
| getObject | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x | x |
5.1.4 Использование потоков для очень больших значений
С помощьюResultSet возможно получать очень
большие данные типа LONGVARBINARY или LONGVARCHAR.
Методы getBytes и getString возвращают эти данные в
виде одного большого куска (вплоть до пределов, которые можно узнать с помощью
метода Statement.getMaxFieldSize). Тем не менее, может оказаться
удобнее считывать очень большие данные небольшими кусками. Это делается с
помощью потоков (java.io.InputStream), которые возвращаются
некоторыми методами ResultSet. Обратите внимание на то, что к этим потокам надо
обращаться сразу, так как они будут закрыты при следующем вызове
getXXX объекта ResultSet. (Такое поведение диктуется
низкоуровневой реализацией доступа к большим двоичным объектам)
В JDBC API есть три отдельных метода для получения потоков:
getBinaryStreamвозвращает поток байтов "как есть", без какого-либо предварительного преобразования
getAsciiStreamвозвращает поток, состоящий из однобайтовых ASCII-символов.
getUnicodeStreamвозвращает поток двухбайтных символов Unicode.
Следующий пример демонстрирует использование
getAsciiStream:
java.sql.Statement stmt = con.createStatement();
ResultSet r = stmt.executeQuery("SELECT x FROM Table2");
// Теперь считываем колонку 1 результатов кусками по 4 K:
byte buff = new byte[4096];
while (r.next())
{
Java.io.InputStream fin = r.getAsciiStream(1);
for (;;)
{
int size = fin.read(buff);
if (size == -1)
{ // в конце потока
break;
}
// Отослать заполненный буфер в ASCII-поток:
output.write(buff, 0, size);
}
}
5.1.5 Значения NULL в результатах
Для того, чтобы определить, равно ли значение колонки NULL или нет, надо сначала считать значение колонки, а затем использовать методResultSet.wasNull для выяснения этого факта. Значение true
означает, что считанное значение равно NULL.
Значение же, возвращаемое в этом случае методом
ResultSet.getXXX, равно:
nullдля тех из методовgetXXX, которые возвращают объекты (такие методы, какgetString,getBigDecimal,getBytes,getDate,getTime,getTimestamp,getAsciiStream,getUnicodeStream,getBinaryStream,getObject).
- нулевое значение для
getByte,getShort,getInt,getLong,getFloat, andgetDouble.
falseв случаеgetBoolean.
5.1.6 Необязательные или множественные наборы результатов (Result Sets)
Обычно SQL-запросы выполняются либо методомexecuteQuery (который возвращает единственный
ResultSet), либо executeUpdate (который может
использоваться для любых запросов на изменение БД и которые возвращают
количество измененных строк). Тем не менее, в некоторых случаях приложению
заведомо неизвестно, возвратит ли данный запрос результат или нет. Кроме того,
некоторые хранимые процедры могут возвратить несколько наборов данных и/или
счетчиков обновления.
На этот случай в JDBC есть механизм, когда приложение
может обрабатывать произвольную коллекцию наборов результатов или счетчиков
обновления. Этот механизм основан на вызове метода execute и
последующем вызове трех других методов getResultSet,
getUpdateCount и getMoreResults. Эти методы позволяют
приложению получать результаты запроса поочереди и для каждого результата
определять, является ли он набором данных или счетчиком обновлений.
Нет никакой необходимости закрывать
ResultSet; это делается автоматически родительским объектом
Statement, когда последний закрывается, выполняется повторно или
используется для извлечения следующего результата в последовательности
нескольких результатов.
Предыдущий | Содержание | Следующий




Узнай о чем ты на самом деле сейчас думаешь

