| | | | JDBCTM Guide: Getting Started |
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);
}
ResultSet
содержит т.н. курсор, который указывает
на текущую строку данных. Каждый раз, когда выполняется метод next
,
курсор перемещается на одну строку вниз. Изначально курсор спозиционирован перед
первой строкой, и первый вызов next
премещает его на первую строку
(она становится текущей). С каждым успешным вызовом next курсор перемещается
вниз на одну строку, начиная с самой верхней в ResultSet
.
Курсор сохраняется до тех пор, пока не закроется объект
ResultSet
или его родительский объект Statement
.
В SQL курсор для результирующей таблицы имеет имя. Если
БД поддерживает позиционированные обновления или позиционированные удаления, то
командам обновления или удаления можно передать в качестве параметра имя
курсора. Это имя может быть получено с помощью вызова
getCursorName
.
Заметим, что не все СУБД поддерживают позиционированные
обновления или удаления. Чтобы узнать, поддерживает ли данное соединение эти
операции или нет, можно вызвать методы
DatabaseMetaData.supportsPositionedDelete
и
supportsPositionedUpdate
.
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
.
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 |
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); } }
ResultSet.wasNull
для выяснения этого факта. Значение true
означает, что считанное значение равно NULL.
Значение же, возвращаемое в этом случае методом
ResultSet.getXXX
, равно:
null
для тех из методов getXXX
, которые
возвращают объекты (такие методы, как getString
,
getBigDecimal
, getBytes
, getDate
,
getTime
, getTimestamp
, getAsciiStream
,
getUnicodeStream
, getBinaryStream
,
getObject
). getByte
, getShort
,
getInt
, getLong
, getFloat
, and
getDouble.
false
в случае getBoolean
. executeQuery
(который возвращает единственный
ResultSet
), либо executeUpdate
(который может
использоваться для любых запросов на изменение БД и которые возвращают
количество измененных строк). Тем не менее, в некоторых случаях приложению
заведомо неизвестно, возвратит ли данный запрос результат или нет. Кроме того,
некоторые хранимые процедры могут возвратить несколько наборов данных и/или
счетчиков обновления.
На этот случай в JDBC есть механизм, когда приложение
может обрабатывать произвольную коллекцию наборов результатов или счетчиков
обновления. Этот механизм основан на вызове метода execute
и
последующем вызове трех других методов getResultSet
,
getUpdateCount
и getMoreResults
. Эти методы позволяют
приложению получать результаты запроса поочереди и для каждого результата
определять, является ли он набором данных или счетчиком обновлений.
Нет никакой необходимости закрывать
ResultSet
; это делается автоматически родительским объектом
Statement
, когда последний закрывается, выполняется повторно или
используется для извлечения следующего результата в последовательности
нескольких результатов.