JDBC ResultSet на Java
Интерфейс Java JDBC ResultSet представляет результат запроса к базе данных. Текст о запросах показывает, как результат запроса возвращается как java.sql.ResultSet. Затем этот ResultSet повторяется для проверки результата.
ResultSet содержит записи
JDBC ResultSet содержит записи. Каждая запись содержит набор столбцов. Каждая запись содержит одинаковое количество столбцов, хотя не все столбцы могут иметь значение. Столбец может иметь нулевое значение. Вот иллюстрация JDBC ResultSet:
Этот ResultSet имеет 3 разных столбца(имя, возраст, пол) и 3 записи с разными значениями для каждого столбца.
Создание ResultSet
Вы создаете ResultSet, выполняя Statement или PreparedStatement, например так:
Тип ResultSet, параллелизм и удерживаемость
Когда вы создаете ResultSet, вы можете установить три атрибута. Эти:
- Тип
- совпадение
- Holdability
Вы устанавливаете их уже при создании Statement или PreparedStatement, например так:
Что именно означают эти атрибуты, объясняется далее в этом тексте. Но теперь вы сейчас, где их указать.
Итерация
Для итерации ResultSet вы используете его метод next(). Метод next() возвращает значение true, если ResultSet имеет следующую запись, и перемещает ResultSet, чтобы он указывал на следующую запись. Если больше не было записей, next() возвращает false, и вы больше не можете. Как только метод next() вернул false, вы не должны больше его вызывать. Это может привести к исключению.
Вот пример итерации ResultSet с использованием метода next():
Как видите, метод next() на самом деле вызывается до доступа к первой записи. Это означает, что ResultSet начинает указывать перед первой записью. После того, как next() был вызван один раз, он указывает на первую запись.
Точно так же, когда next() вызывается и возвращает false, ResultSet фактически указывает после последней записи.
Вы не можете получить количество строк в ResultSet, за исключением случаев, когда вы выполняете все итерации по нему и подсчитываете строки. Однако, если ResultSet предназначен только для пересылки, вы не сможете впоследствии перемещаться назад. Даже если бы вы могли двигаться назад, это был бы медленный способ подсчета строк в ResultSet. Вам лучше структурировать свой код так, что вам не нужно заранее знать количество записей.
Доступ к значениям столбца
При переборе ResultSet вы хотите получить доступ к значениям столбцов каждой записи. Вы делаете это, вызывая один или несколько методов getXXX(). Вы передаете имя столбца, чтобы получить значение многих методов getXXX(). Например:
Есть много методов getXXX(), которые вы можете вызвать, которые возвращают значение столбца в виде определенного типа данных, например String, int, long, double, BigDecimal и т. Д. Все они берут имя столбца, чтобы получить столбец значение для, как параметр. Вот список быстрых примеров этих методов getXXX():
Методы getXXX() также существуют в версиях, которые принимают индекс столбца вместо имени столбца. Например:
Индекс столбца обычно зависит от индекса столбца в операторе SQL. Например, оператор SQL
имеет три столбца. Имя столбца указывается первым и, следовательно, будет иметь индекс 1 в ResultSet. Возраст столбца будет иметь индекс 2, а коэффициент столбца будет иметь индекс 3.
Иногда вы не знаете индекс определенного столбца раньше времени. Например, если вы используете SQL-запрос select * from, вы не знаете последовательность столбцов.
Если вы не знаете индекс определенного столбца, вы можете найти индекс этого столбца, используя метод ResultSet.findColumn(String columnName), например:
ResultSet Types
ResultSet может быть определенного типа. Тип определяет некоторые характеристики и возможности ResultSet.
Не все типы поддерживаются всеми базами данных и драйверами JDBC. Вам придется проверить свою базу данных и драйвер JDBC, чтобы увидеть, поддерживает ли он тип, который вы хотите использовать. Метод DatabaseMetaData.supportsResultSetType(int type) возвращает true или false в зависимости от того, поддерживается данный тип или нет. Класс DatabaseMetaData описан в следующем тексте.
На момент написания статьи существует три типа ResultSet:
- ResultSet.TYPE_FORWARD_ONLY
- ResultSet.TYPE_SCROLL_INSENSITIVE
- ResultSet.TYPE_SCROLL_SENSITIVE
Тип по умолчанию – TYPE_FORWARD_ONLY
TYPE_FORWARD_ONLY означает, что ResultSet можно перемещать только вперед. То есть вы можете перемещаться только из строки 1, строки 2, строки 3 и т. Д. В ResultSet вы не можете двигаться назад.
TYPE_SCROLL_INSENSITIVE означает, что ResultSet можно перемещать(прокручивать) как вперед, так и назад. Вы также можете перейти к позиции относительно текущей позиции или перейти к абсолютной позиции. ResultSet нечувствителен к изменениям в базовом источнике данных, пока ResultSet открыт. То есть, если запись в ResultSet изменяется в базе данных другим потоком или процессом, она не будет отражена в уже открытых ResulsSet этого типа.
TYPE_SCROLL_SENSITIVE означает, что ResultSet можно перемещать(прокручивать) как вперед, так и назад. Вы также можете перейти к позиции относительно текущей позиции или перейти к абсолютной позиции. ResultSet чувствителен к изменениям в базовом источнике данных, пока ResultSet открыт. То есть, если запись в ResultSet изменяется в базе данных другим потоком или процессом, она будет отражена в уже открытых ResulsSet этого типа.
Методы навигации
Интерфейс ResultSet содержит следующие методы навигации. Помните, что не все методы работают со всеми типами ResultSet. Какие методы работают, зависит от вашей базы данных, драйвера JDBC и типа ResultSet.
Интерфейс ResultSet также содержит набор методов, которые вы можете использовать для запроса текущей позиции ResultSet. Эти:
Наконец, интерфейс ResultSet также содержит метод для обновления строки изменениями базы данных, если ResultSet чувствителен к изменениям.
Concurrency
Параллельность ResultSet определяет, может ли ResultSet обновляться или только считываться.
Некоторые базы данных и драйверы JDBC поддерживают обновление ResultSet, но не все базы данных и драйверы JDBC поддерживают это. Метод DatabaseMetaData.supportsResultSetConcurrency(int concurrency) возвращает значение true или false в зависимости от того, поддерживается данный режим параллелизма или нет. Класс DatabaseMetaData описан в следующем тексте.
ResultSet может иметь один из двух уровней параллелизма:
- ResultSet.CONCUR_READ_ONLY
- ResultSet.CONCUR_UPDATABLE
CONCUR_READ_ONLY означает, что ResultSet может быть прочитан только.
CONCUR_UPDATABLE означает, что ResultSet может быть прочитан и обновлен.
Обновление ResultSet
Если ResultSet является обновляемым, вы можете обновить столбцы каждой строки в ResultSet. Вы делаете это, используя множество методов updateXXX(). Например:
Вы также можете обновить столбец, используя индекс столбца вместо имени столбца. Вот пример:
Обратите внимание на вызов updateRow(). Когда вызывается updateRow(), база данных обновляется со значениями строки. Если вы не вызываете этот метод, значения, обновленные в ResultSet, никогда не отправляются в базу данных. Если вы вызываете updateRow() внутри транзакции, данные фактически не фиксируются в базе данных, пока транзакция не будет зафиксирована.
Вставка строк в ResultSet
Если ResultSet является обновляемым, в него также можно вставлять строки. Вы делаете это:
- вызов ResultSet.moveToInsertRow()
- обновить значения столбца строки
- вызвать ResultSet.insertRow()
Строка, на которую указывает после вызова moveToInsertRow(), является специальной строкой, буфером, который можно использовать для построения строки, пока все значения столбцов не будут установлены в строке правильно.
Когда строка будет готова для вставки в ResultSet, вызовите метод insertRow().
После вставки строки ResultSet по-прежнему указывает на строку вставки. Однако вы не можете быть уверены, что произойдет, если вы попытаетесь получить к нему доступ после вставки строки. Поэтому вы должны переместить ResultSet в правильную позицию после вставки новой строки. Если вам нужно вставить другую строку, явно вызовите moveToInsertRow(), чтобы сообщить об этом ResultSet.
Удерживаемость ResultSet
Удерживаемость ResultSet определяет, будет ли ResultSet закрыт при вызове метода commit() базового соединения.
Что такое resultset как с ним работать
A ResultSet object maintains a cursor pointing to its current row of data. Initially the cursor is positioned before the first row. The next method moves the cursor to the next row, and because it returns false when there are no more rows in the ResultSet object, it can be used in a while loop to iterate through the result set.
A default ResultSet object is not updatable and has a cursor that moves forward only. Thus, you can iterate through it only once and only from the first row to the last row. It is possible to produce ResultSet objects that are scrollable and/or updatable. The following code fragment, in which con is a valid Connection object, illustrates how to make a result set that is scrollable and insensitive to updates by others, and that is updatable. See ResultSet fields for other options. The ResultSet interface provides getter methods ( getBoolean , getLong , and so on) for retrieving column values from the current row. Values can be retrieved using either the index number of the column or the name of the column. In general, using the column index will be more efficient. Columns are numbered from 1. For maximum portability, result set columns within each row should be read in left-to-right order, and each column should be read only once.
For the getter methods, a JDBC driver attempts to convert the underlying data to the Java type specified in the getter method and returns a suitable Java value. The JDBC specification has a table showing the allowable mappings from SQL types to Java types that can be used by the ResultSet getter methods.
Column names used as input to getter methods are case insensitive. When a getter method is called with a column name and several columns have the same name, the value of the first matching column will be returned. The column name option is designed to be used when column names are used in the SQL query that generated the result set. For columns that are NOT explicitly named in the query, it is best to use column numbers. If column names are used, the programmer should take care to guarantee that they uniquely refer to the intended columns, which can be assured with the SQL AS clause.
A set of updater methods were added to this interface in the JDBC 2.0 API (Java™ 2 SDK, Standard Edition, version 1.2). The comments regarding parameters to the getter methods also apply to parameters to the updater methods.
- to update a column value in the current row. In a scrollable ResultSet object, the cursor can be moved backwards and forwards, to an absolute position, or to a position relative to the current row. The following code fragment updates the NAME column in the fifth row of the ResultSet object rs and then uses the method updateRow to update the data source table from which rs was derived.
- to insert column values into the insert row. An updatable ResultSet object has a special row associated with it that serves as a staging area for building a row to be inserted. The following code fragment moves the cursor to the insert row, builds a three-column row, and inserts it into rs and into the data source table using the method insertRow .
A ResultSet object is automatically closed when the Statement object that generated it is closed, re-executed, or used to retrieve the next result from a sequence of multiple results.
Interface ResultSet
A ResultSet object maintains a cursor pointing to its current row of data. Initially the cursor is positioned before the first row. The next method moves the cursor to the next row, and because it returns false when there are no more rows in the ResultSet object, it can be used in a while loop to iterate through the result set.
A default ResultSet object is not updatable and has a cursor that moves forward only. Thus, you can iterate through it only once and only from the first row to the last row. It is possible to produce ResultSet objects that are scrollable and/or updatable. The following code fragment, in which con is a valid Connection object, illustrates how to make a result set that is scrollable and insensitive to updates by others, and that is updatable. See ResultSet fields for other options. The ResultSet interface provides getter methods ( getBoolean , getLong , and so on) for retrieving column values from the current row. Values can be retrieved using either the index number of the column or the name of the column. In general, using the column index will be more efficient. Columns are numbered from 1. For maximum portability, result set columns within each row should be read in left-to-right order, and each column should be read only once.
For the getter methods, a JDBC driver attempts to convert the underlying data to the Java type specified in the getter method and returns a suitable Java value. The JDBC specification has a table showing the allowable mappings from SQL types to Java types that can be used by the ResultSet getter methods.
Column names used as input to getter methods are case insensitive. When a getter method is called with a column name and several columns have the same name, the value of the first matching column will be returned. The column name option is designed to be used when column names are used in the SQL query that generated the result set. For columns that are NOT explicitly named in the query, it is best to use column numbers. If column names are used, the programmer should take care to guarantee that they uniquely refer to the intended columns, which can be assured with the SQL AS clause.
A set of updater methods were added to this interface in the JDBC 2.0 API (Java 2 SDK, Standard Edition, version 1.2). The comments regarding parameters to the getter methods also apply to parameters to the updater methods.
- to update a column value in the current row. In a scrollable ResultSet object, the cursor can be moved backwards and forwards, to an absolute position, or to a position relative to the current row. The following code fragment updates the NAME column in the fifth row of the ResultSet object rs and then uses the method updateRow to update the data source table from which rs was derived.
- to insert column values into the insert row. An updatable ResultSet object has a special row associated with it that serves as a staging area for building a row to be inserted. The following code fragment moves the cursor to the insert row, builds a three-column row, and inserts it into rs and into the data source table using the method insertRow .
A ResultSet object is automatically closed when the Statement object that generated it is closed, re-executed, or used to retrieve the next result from a sequence of multiple results.
5 — ResultSet (набор данных)
Набор данных результата (result set) является таблицей с заголовками колонок и соответствующих значений, возвращенных запросом. Например, если мы имеем запрос SELECT a, b, c FROM Table1 , то набор результата будет в следующей форме:
Следующий фрагмент кода демонстрирует выполнение SQL-запроса, который возвращает коллекцию строк, в которой колонка 1 — это int , колонка 2 — String и колонка 3 — массив байтов:
5.1.1 Строки и курсоры
Курсор сохраняется до тех пор, пока не закроется объект ResultSet или его родительский объект Statement .
В SQL курсор для результирующей таблицы имеет имя. Если БД поддерживает позиционированные обновления или позиционированные удаления, то командам обновления или удаления можно передать в качестве параметра имя курсора. Это имя может быть получено с помощью вызова getCursorName .
Заметим, что не все СУБД поддерживают позиционированные обновления или удаления. Чтобы узнать, поддерживает ли данное соединение эти операции или нет, можно вызвать методы DatabaseMetaData.supportsPositionedDelete и supportsPositionedUpdate .
5.1.2 Колонки
Для указания колонки можно использовать либо ее имя, либо ее номер. Например, если вторая колонка объекта ResultSet rs называется «title» и хранит строковое значение, то извлечь его можно одним из двух способов:
Имейте ввиду, что колонки нумеруются слева направо, начиная с 1. Имена колонок в вызове методов getXXX нечувствительны к регистру букв.
Вариант с использование имен колонок существует для того, чтобы пользователь задавал методам getXXX те же имена колонок, что он использует в запросе. Если выражение select не указывает имена колонок (например » select * from table1 » или в случаях, когда колонка вычисляется) должны использоваться номера колонок. В этих случаях пользователь не может знать наверняка имена колонок.
В нектороых случаях имена двух колонок могут совпадать. Тогда при использовании имен колонок в методах getXXX возвращается значение первой подходящей колонки. Таким образом, чтобы считать значение других колонок с таким же именем, надо использовать индексы колонок. Кроме того, использование индексов немного эффективнее.
Информацию о колонках в ResultSet можно получить с помощтю вызова ResultSet.getMetaData . Возвращаемый объект ResultSetMetaData содержит информацию о количестве, типах и свойствах колонок объекта ResultSet .
Если известно имя колонки, но не ее индекс, то для поиска номера колонки можно использовать метод findColumn .
5.1.3 Типы данных и их преобразование
Следующая таблица показывает, какие типы данных различные методы getXXX могут считывать и какие JDBC-типы (SQL-типы) рекомендуются для этих методов. Знак x означает, что метод getXXX подходит к соответствующему типу данных; знак X означает рекомендуемый метод getXXX для данного типа. Например, значение LONGVARCHAR можно извлечь любым из методов getXXX кроме getBytes и getBinaryStream , но рекомендуется использовать методы getAsciiStream и getUnicodeStream . Метод getObject возвращает любой тип данных как Object и используется в тех случаях, когда соответствующий низкоуровневый тип данных является специфичным для данной СУБД или когда приложению необходимо принять любой тип данных.
5.1.4 Использование потоков для очень больших значений
В JDBC API есть три отдельных метода для получения потоков:
-
getBinaryStream возвращает поток байтов «как есть», без какого-либо предварительного преобразования
Эти потоки отличаются от обычных потоков Java, которые возвращают нетипизированные байты, и могут, например, быть ASCII- или Unicode-символами.
Следующий пример демонстрирует использование getAsciiStream :
5.1.5 Значения NULL в результатах
Значение же, возвращаемое в этом случае методом ResultSet.getXXX , равно:
-
null для тех из методов getXXX , которые возвращают объекты (такие методы, как getString , getBigDecimal , getBytes , getDate , getTime , getTimestamp , getAsciiStream , getUnicodeStream , getBinaryStream , getObject ).
5.1.6 Необязательные или множественные наборы результатов (Result Sets)
На этот случай в JDBC есть механизм, когда приложение может обрабатывать произвольную коллекцию наборов результатов или счетчиков обновления. Этот механизм основан на вызове метода execute и последующем вызове трех других методов getResultSet , getUpdateCount и getMoreResults . Эти методы позволяют приложению получать результаты запроса поочереди и для каждого результата определять, является ли он набором данных или счетчиком обновлений.
Нет никакой необходимости закрывать ResultSet ; это делается автоматически родительским объектом Statement , когда последний закрывается, выполняется повторно или используется для извлечения следующего результата в последовательности нескольких результатов.