Spec-Zone .ru
спецификации, руководства, описания, API
|
Следующий метод, CoffeesTable.viewTable
выводит содержание COFFEES
таблицы, и демонстрируют использование ResultSet
объекты и курсоры:
public static void viewTable(Connection con, String dbName) throws SQLException { Statement stmt = null; String query = "select COF_NAME, SUP_ID, PRICE, " + "SALES, TOTAL " + "from " + dbName + ".COFFEES"; try { stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(query); while (rs.next()) { String coffeeName = rs.getString("COF_NAME"); int supplierID = rs.getInt("SUP_ID"); float price = rs.getFloat("PRICE"); int sales = rs.getInt("SALES"); int total = rs.getInt("TOTAL"); System.out.println(coffeeName + "\t" + supplierID + "\t" + price + "\t" + sales + "\t" + total); } } catch (SQLException e ) { JDBCTutorialUtilities.printSQLException(e); } finally { if (stmt != null) { stmt.close(); } } }
A ResultSet
объект является таблицей данных, представляющих набор результатов базы данных, который обычно сгенерирован, выполняя оператор, который запрашивает базу данных. Например, CoffeeTables.viewTable
метод создает a ResultSet
, rs
, когда это выполняет запрос через Statement
объект, stmt
. Отметьте это a ResultSet
объект может быть создан через любой объект, который реализует Statement
интерфейс, включая PreparedStatement
, CallableStatement
, и RowSet
.
Вы получаете доступ к данным в a ResultSet
объект через курсор. Отметьте, что этот курсор не является курсором базы данных. Этот курсор является указателем, который указывает на одну строку данных в ResultSet
. Первоначально, курсор располагается перед первой строкой. Метод ResultSet.next
перемещает курсор в следующую строку. Этот метод возвраты false
если курсор располагается после последней строки. Этот метод неоднократно вызывает ResultSet.next
метод с a while
цикл, чтобы выполнить итерации через все данные в ResultSet
.
Эта страница затрагивает следующие темы:
ResultSet
интерфейс обеспечивает методы для получения и управления результатами выполняемых запросов, и ResultSet
у объектов могут быть различная функциональность и характеристики. Эти характеристики являются типом, параллелизмом, и курсором holdability.
Тип a ResultSet
объект определяет уровень своей функциональности в двух областях: пути, которыми курсором можно управлять, и как параллельные изменения, произведенные в базовом источнике данных, отражаются ResultSet
объект.
Чувствительность a ResultSet
объект определяется одним из три отличающийся ResultSet
типы:
TYPE_FORWARD_ONLY
: Набор результатов не может быть прокручен; его курсор продвигается только до первой строки к после последней строки. Строки, содержавшиеся в наборе результатов, зависят от того, как базовая база данных генерирует результаты. Таким образом, это содержит строки, которые удовлетворяют запрос или во время, запрос выполняется или поскольку строки получаются.TYPE_SCROLL_INSENSITIVE
: Результат может быть прокручен; его курсор может переместить обоих вперед и назад относительно текущей позиции, и она может переместиться в абсолютную позицию. Набор результатов нечувствителен к изменениям, произведенным в базовом источнике данных, в то время как это открыто. Это содержит строки, которые удовлетворяют запрос или во время, запрос выполняется или поскольку строки получаются.TYPE_SCROLL_SENSITIVE
: Результат может быть прокручен; его курсор может переместить обоих вперед и назад относительно текущей позиции, и она может переместиться в абсолютную позицию. Набор результатов отражает изменения, произведенные в базовом источнике данных, в то время как набор результатов остается открытым.Значение по умолчанию ResultSet
тип TYPE_FORWARD_ONLY
.
Отметьте: Не все базы данных и драйверы JDBC поддерживают все ResultSet
типы. Метод DatabaseMetaData.supportsResultSetType
возвраты true
если указанное ResultSet
тип поддерживается и false
иначе.
Параллелизм a ResultSet
объект определяет, какой уровень функциональности обновления поддерживается.
Есть два уровня параллелизма:
CONCUR_READ_ONLY
: ResultSet
объект не может быть обновлен, используя ResultSet
интерфейс.CONCUR_UPDATABLE
: ResultSet
объект может быть обновлен, используя ResultSet
интерфейс.Значение по умолчанию ResultSet
параллелизм CONCUR_READ_ONLY
.
Отметьте: Не все драйверы JDBC и базы данных поддерживают параллелизм. Метод DatabaseMetaData.supportsResultSetConcurrency
возвраты true
если указанный уровень параллелизма поддерживается драйвером и false
иначе.
Метод CoffeesTable.modifyPrices
демонстрирует, как использовать a ResultSet
возразите, чей уровень параллелизма CONCUR_UPDATABLE
.
Вызов метода Connection.commit
может закрыться ResultSet
объекты, которые были созданы во время текущей транзакции. В некоторых случаях, однако, это, возможно, не требуемое поведение. ResultSet
свойство holdability передает управлению приложением ли ResultSet
объекты (курсоры) закрываются, когда фиксацию вызывают.
Следующий ResultSet
константы могут быть предоставлены Connection
методы createStatement
, prepareStatement
, и prepareCall
:
HOLD_CURSORS_OVER_COMMIT
: ResultSet
курсоры не закрываются; они - holdable: они считаются открытые когда метод commit
вызывается. Курсоры Holdable могли бы быть идеальными если Ваше использование приложения, главным образом только для чтения ResultSet
объекты.CLOSE_CURSORS_AT_COMMIT
: ResultSet
объекты (курсоры) закрываются когда commit
метод вызывают. Заключительные курсоры, когда этот метод вызывают, могут привести к лучшей производительности для некоторых приложений.Курсор значения по умолчанию holdability изменяется в зависимости от Вашего DBMS.
Отметьте: Не все драйверы JDBC и базы данных поддерживают holdable и non-holdable курсоры. Следующий метод, JDBCTutorialUtilities.cursorHoldabilitySupport
, выводит курсор значения по умолчанию holdability ResultSet
объекты и ли HOLD_CURSORS_OVER_COMMIT
и CLOSE_CURSORS_AT_COMMIT
поддерживаются:
public static void cursorHoldabilitySupport(Connection conn) throws SQLException { DatabaseMetaData dbMetaData = conn.getMetaData(); System.out.println("ResultSet.HOLD_CURSORS_OVER_COMMIT = " + ResultSet.HOLD_CURSORS_OVER_COMMIT); System.out.println("ResultSet.CLOSE_CURSORS_AT_COMMIT = " + ResultSet.CLOSE_CURSORS_AT_COMMIT); System.out.println("Default cursor holdability: " + dbMetaData.getResultSetHoldability()); System.out.println("Supports HOLD_CURSORS_OVER_COMMIT? " + dbMetaData.supportsResultSetHoldability( ResultSet.HOLD_CURSORS_OVER_COMMIT)); System.out.println("Supports CLOSE_CURSORS_AT_COMMIT? " + dbMetaData.supportsResultSetHoldability( ResultSet.CLOSE_CURSORS_AT_COMMIT)); }
ResultSet
интерфейс объявляет методы метода get (например, getBoolean
и getLong
) для того, чтобы получить значения столбцов от текущей строки. Можно получить значения, используя или индекс столбца или псевдоним или имя столбца. Столбец индексирует, обычно более эффективно. Столбцы нумеруются от 1. Для максимальной мобильности столбцы набора результатов в каждой строке должны быть считаны в слева направо порядке, и каждый столбец должен быть только для чтения однажды.
Например, следующий метод, CoffeesTable.alternateViewTable
, получает значения столбцов числом:
public static void alternateViewTable(Connection con) throws SQLException { Statement stmt = null; String query = "select COF_NAME, SUP_ID, PRICE, " + "SALES, TOTAL from COFFEES"; try { stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(query); while (rs.next()) { String coffeeName = rs.getString(1); int supplierID = rs.getInt(2); float price = rs.getFloat(3); int sales = rs.getInt(4); int total = rs.getInt(5); System.out.println(coffeeName + "\t" + supplierID + "\t" + price + "\t" + sales + "\t" + total); } } catch (SQLException e ) { JDBCTutorialUtilities.printSQLException(e); } finally { if (stmt != null) { stmt.close(); } } }
Строки, привыкшие как входной к методам метода get, являются нечувствительными к регистру. Когда метод метода get вызывают со строкой, и больше чем у одного столбца есть тот же самый псевдоним или имя как строка, значение первого столбца соответствия возвращается. Опция, чтобы использовать строку в противоположность целому числу разрабатывается, чтобы использоваться, когда псевдонимы столбца и имена используются в SQL-запросе, который генерировал набор результатов. Для столбцов, которые явно не называют в запросе (например, select * from COFFEES
) лучше использовать номера столбца. Если имена столбцов будут использоваться, то разработчик должен гарантировать, что они уникально обращаются к намеченным столбцам при использовании псевдонимов столбца. Псевдоним столбца эффективно переименовывает столбец набора результатов. Чтобы определить псевдоним столбца, используйте SQL AS
пункт в SELECT
оператор.
Метод метода get соответствующего типа получает значение в каждом столбце. Например, в методе CoffeeTables.viewTable
, первый столбец в каждой строке ResultSet
rs
COF_NAME
, который хранит значение типа SQL VARCHAR
. Метод для того, чтобы получить значение типа SQL VARCHAR
getString
. Второй столбец в каждой строке хранит значение типа SQL INTEGER
, и метод для того, чтобы получить значения того типа getInt
.
Отметьте это хотя метод getString
рекомендуется для того, чтобы получить типы SQL CHAR
и VARCHAR
, возможно получить любой из основных типов SQL с этим. Получение всех значений с getString
может быть очень полезным, но у этого также есть свои ограничения. Например, если это используется, чтобы получить числовой тип, getString
преобразовывает числовое значение в Java String
объект, и значение должны быть преобразованы назад в числовой тип прежде, чем на этом можно будет управлять как число. В случаях, где значение обрабатывается как строка так или иначе, нет никакого недостатка. Кроме того, если Вы хотите, чтобы приложение получило значения какого-либо стандартного типа SQL кроме типов SQL3, используйте getString
метод.
Как упомянуто ранее, Вы получаете доступ к данным в a ResultSet
объект через курсор, который указывает на одну строку в ResultSet
объект. Однако, когда a ResultSet
объект сначала создается, курсор располагается перед первой строкой. Метод CoffeeTables.viewTable
перемещает курсор, вызывая ResultSet.next
метод. Есть другие методы, доступные, чтобы переместить курсор:
next
: Перемещается курсор передают одну строку. Возвраты true
если курсор теперь располагается на строку и false
если курсор располагается после последней строки.previous
: Перемещает курсор назад одна строка. Возвраты true
если курсор теперь располагается на строку и false
если курсор располагается перед первой строкой.first
: Перемещает курсор в первую строку в ResultSet
объект. Возвраты true
если курсор теперь располагается на первую строку и false
если ResultSet
объект не содержит строк.last:
: Перемещает курсор в последнюю строку в ResultSet
объект. Возвраты true
если курсор теперь располагается на последнюю строку и false
если ResultSet
объект не содержит строк.beforeFirst
: Располагает курсор в начале ResultSet
объект, перед первой строкой. Если ResultSet
объект не содержит строк, этот метод не имеет никакого эффекта.afterLast
: Располагает курсор в конце ResultSet
объект, после последней строки. Если ResultSet
объект не содержит строк, этот метод не имеет никакого эффекта.relative(int rows)
: Перемещает курсор относительно его текущей позиции.absolute(int row)
: Располагает курсор на строку, определенную параметром row
.Отметьте что чувствительность значения по умолчанию a ResultSet
TYPE_FORWARD_ONLY
, что означает, что это не может быть прокручено; невозможно вызвать ни один из этих методов, которые перемещают курсор, кроме next
, если Ваш ResultSet
не может быть прокручен. Метод CoffeesTable.modifyPrices
, описанный в следующем разделе, демонстрирует, как можно переместить курсор a ResultSet
.
Невозможно обновить значение по умолчанию ResultSet
объект, и можно только переместить его курсор вперед. Однако, можно создать ResultSet
объекты, которые могут быть прокручены (курсор может переместиться назад или переместиться в абсолютную позицию), и обновленный.
Следующий метод, CoffeesTable.modifyPrices
, умножается PRICE
столбец каждой строки параметром percentage
:
public void modifyPrices(float percentage) throws SQLException { Statement stmt = null; try { stmt = con.createStatement(); stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet uprs = stmt.executeQuery( "SELECT * FROM " + dbName + ".COFFEES"); while (uprs.next()) { float f = uprs.getFloat("PRICE"); uprs.updateFloat( "PRICE", f * percentage); uprs.updateRow(); } } catch (SQLException e ) { JDBCTutorialUtilities.printSQLException(e); } finally { if (stmt != null) { stmt.close(); } } }
Поле ResultSet.TYPE_SCROLL_SENSITIVE
создает a ResultSet
возразите, чей курсор может переместить обоих вперед и назад относительно текущей позиции и к абсолютной позиции. Поле ResultSet.CONCUR_UPDATABLE
создает a ResultSet
объект, который может быть обновлен. См. ResultSet
Javadoc для других полей можно определить, чтобы изменить поведение ResultSet
объекты.
Метод ResultSet.updateFloat
обновляет указанный столбец (в этом примере, PRICE
с указанным float
значение в строке, где курсор располагается. ResultSet
содержит различные updater методы, которые позволяют Вам обновить значения столбцов различных типов данных. Однако, ни один из этих updater методов не изменяет базу данных; следует вызвать метод ResultSet.updateRow
обновить базу данных.
Statement
, PreparedStatement
и CallableStatement
у объектов есть список команд, который связывается с ними. Этот список может содержать операторы для того, чтобы обновить, вставить, или удалить строку; и это может также содержать операторы DDL такой как CREATE TABLE
и DROP TABLE
. Это не может, однако, содержать оператор, который произвел бы a ResultSet
объект, такой как a SELECT
оператор. Другими словами список может содержать только операторы, которые производят количество обновления.
Список, который связывается с a Statement
объект при его создании, первоначально пусто. Можно добавить команды SQL к этому списку с методом addBatch
и освободите это с методом clearBatch
. Когда Вы закончили добавлять операторы к списку, вызовите метод executeBatch
передаться им всем к базе данных, которая будет выполняться как модуль, или пакет.
Например, следующий метод CoffeesTable.batchUpdate
добавляют четыре строки к COFFEES
таблица с пакетным обновлением:
public void batchUpdate() throws SQLException { Statement stmt = null; try { this.con.setAutoCommit(false); stmt = this.con.createStatement(); stmt.addBatch( "INSERT INTO COFFEES " + "VALUES('Amaretto', 49, 9.99, 0, 0)"); stmt.addBatch( "INSERT INTO COFFEES " + "VALUES('Hazelnut', 49, 9.99, 0, 0)"); stmt.addBatch( "INSERT INTO COFFEES " + "VALUES('Amaretto_decaf', 49, " + "10.99, 0, 0)"); stmt.addBatch( "INSERT INTO COFFEES " + "VALUES('Hazelnut_decaf', 49, " + "10.99, 0, 0)"); int [] updateCounts = stmt.executeBatch(); this.con.commit(); } catch(BatchUpdateException b) { JDBCTutorialUtilities.printBatchUpdateException(b); } catch(SQLException ex) { JDBCTutorialUtilities.printSQLException(ex); } finally { if (stmt != null) { stmt.close(); } this.con.setAutoCommit(true); } }
Следующая строка отключает режим автоматической фиксации для Connection
возразите доводу "против" так, чтобы транзакция автоматически не фиксировалась или откатывалась когда метод executeBatch
вызывается.
this.con.setAutoCommit(false);
Чтобы учесть корректную обработку ошибок, следует всегда отключать режим автоматической фиксации прежде, чем начать пакетное обновление.
Метод Statement.addBatch
добавляет команда к списку команд, связанных с Statement
объект stmt
. В этом примере эти команды - все INSERT INTO
операторы, каждый добавляющий строку, состоящую из пяти значений столбцов. Значения для столбцов COF_NAME
и PRICE
имя кофе и его цены, соответственно. Второе значение в каждой строке 49, потому что это - идентификационный номер для поставщика, Превосходящего Кофе. Последние два значения, записи для столбцов SALES
и TOTAL
, все начинают быть нулем, потому что еще не было никаких продаж. (SALES
число фунтов кофе этой строки, проданного на текущей неделе; TOTAL
общее количество всех совокупных продаж этого кофе.)
Следующая строка отправляет четыре команды SQL, которые были добавлены к его списку команд к базе данных, которая будет выполняться как пакет:
int [] updateCounts = stmt.executeBatch();
Отметьте это stmt
использует метод executeBatch
отправить пакет вставок, не метод executeUpdate
, который отправляет только одну команду и возвращает единственное количество обновления. DBMS выполняет команды в порядке, в котором они были добавлены к списку команд, таким образом, это сначала добавит строку значений для Amaretto, затем добавьте строку для Лесного ореха, тогда кофе без кофеина Amaretto, и наконец кофе без кофеина Лесного ореха. Если все четыре команды выполнятся успешно, то DBMS возвратит счет обновления для каждой команды в порядке, в котором это выполнялось. Количества обновления, которые указывают, на сколько строк влияла каждая команда, сохранены в массиве updateCounts
.
Если все четыре из команд в пакете выполняются успешно, updateCounts
будет содержать четыре значения, все из которых 1, потому что вставка влияет на одну строку. Список команд, связанных с stmt
теперь будет пусто, потому что эти четыре команды, добавленные ранее, были отправлены базе данных когда stmt
названный методом executeBatch
. Можно в любое время явно освободить этот список от команд с методом clearBatch
.
Connection.commit
метод делает пакет из обновлений к COFFEES
постоянная таблица. Этот метод нужно вызвать явно, потому что режим автоматической фиксации для этого соединения был отключен ранее.
Следующая строка включает режиму автоматической фиксации для тока Connection
объект.
this.con.setAutoCommit(true);
Теперь каждый оператор в примере будет автоматически фиксироваться после того, как это будет выполнено, и это больше не должно вызвать метод commit
.
Также возможно иметь параметризованное пакетное обновление, как показано в следующем фрагменте кода, где con
a Connection
объект:
con.setAutoCommit(false); PreparedStatement pstmt = con.prepareStatement( "INSERT INTO COFFEES VALUES( " + "?, ?, ?, ?, ?)"); pstmt.setString(1, "Amaretto"); pstmt.setInt(2, 49); pstmt.setFloat(3, 9.99); pstmt.setInt(4, 0); pstmt.setInt(5, 0); pstmt.addBatch(); pstmt.setString(1, "Hazelnut"); pstmt.setInt(2, 49); pstmt.setFloat(3, 9.99); pstmt.setInt(4, 0); pstmt.setInt(5, 0); pstmt.addBatch(); // ... and so on for each new // type of coffee int [] updateCounts = pstmt.executeBatch(); con.commit(); con.setAutoCommit(true);
Вы получите a BatchUpdateException
когда Вы вызываете метод executeBatch
если (1) один из SQL-операторов, которые Вы добавили к пакету, производит набор результатов (обычно запрос) или (2), один из SQL-операторов в пакете не выполняется успешно по некоторой другой причине.
Недопустимо добавить запрос (a SELECT
оператор) к пакету команд SQL, потому что метод executeBatch
, то, который возвращает массив количеств обновления, ожидает количество обновления от каждого SQL-оператора, который выполняется успешно. Это означает, что только команды, которые возвращают количество обновления (команды такой как INSERT INTO
, UPDATE
, DELETE
) или тот возврат 0 (такой как CREATE TABLE
, DROP TABLE
, ALTER TABLE
) может быть успешно выполнен как пакет с executeBatch
метод.
A BatchUpdateException
содержит массив количеств обновления, который подобен массиву, возвращенному методом executeBatch
. В обоих случаях количества обновления находятся в том же самом порядке как команды, которые произвели их. Это говорит Вам, сколько команд в пакете, выполняемом успешно и которые они. Например, если пять команд выполнились успешно, массив будет содержать пять чисел: первый, являющийся обновлением, значит первую команду, второй, являющийся обновлением, значат вторую команду, и так далее.
BatchUpdateException
получается из SQLException
. Это означает, что можно использовать все методы, доступные SQLException
объект с этим. Следующий метод, JDBCTutorialUtilities.printBatchUpdateException
печатные издания весь из SQLException
информация плюс количества обновления содержится в a BatchUpdateException
объект. Поскольку BatchUpdateException.getUpdateCounts
возвращает массив int
, код использует a for
цикл, чтобы напечатать каждое из количеств обновления:
public static void printBatchUpdateException(BatchUpdateException b) { System.err.println("----BatchUpdateException----"); System.err.println("SQLState: " + b.getSQLState()); System.err.println("Message: " + b.getMessage()); System.err.println("Vendor: " + b.getErrorCode()); System.err.print("Update counts: "); int [] updateCounts = b.getUpdateCounts(); for (int i = 0; i < updateCounts.length; i++) { System.err.print(updateCounts[i] + " "); } }
Отметьте: Не вся поддержка драйверов JDBC, вставляющая новые строки с ResultSet
интерфейс. Если Вы пытаетесь вставить новую строку, и Ваша база данных драйвера JDBC не поддерживает эту функцию, a SQLFeatureNotSupportedException
исключение выдается.
Следующий метод, CoffeesTable.insertRow
, вставляет строку в COFFEES
через a ResultSet
объект:
public void insertRow(String coffeeName, int supplierID, float price, int sales, int total) throws SQLException { Statement stmt = null; try { stmt = con.createStatement( ResultSet.TYPE_SCROLL_SENSITIVE ResultSet.CONCUR_UPDATABLE); ResultSet uprs = stmt.executeQuery( "SELECT * FROM " + dbName + ".COFFEES"); uprs.moveToInsertRow(); uprs.updateString("COF_NAME", coffeeName); uprs.updateInt("SUP_ID", supplierID); uprs.updateFloat("PRICE", price); uprs.updateInt("SALES", sales); uprs.updateInt("TOTAL", total); uprs.insertRow(); uprs.beforeFirst(); } catch (SQLException e ) { JDBCTutorialUtilities.printSQLException(e); } finally { if (stmt != null) { stmt.close(); } } }
Этот пример вызывает Connection.createStatement
метод с двумя параметрами, ResultSet.TYPE_SCROLL_SENSITIVE
и ResultSet.CONCUR_UPDATABLE
. Первое значение включает курсору ResultSet
объект, который будет перемещен оба вперед и назад. Второе значение, ResultSet.CONCUR_UPDATABLE
, требуется, если Вы хотите вставить строки в a ResultSet
объект; это определяет, что может быть обновляемо.
Те же самые соглашения для того, чтобы использовать строки в методах метода get также применяются к updater методам.
Метод ResultSet.moveToInsertRow
перемещает курсор в строку вставки. Строка вставки является специальной строкой, связанной с обновляемым набором результатов. Это - по существу буфер, где новая строка может быть создана, вызывая updater методы до вставки строки в набор результатов. Например, это вызовы метода метод ResultSet.updateString
обновить строку вставки COF_NAME
столбец к Kona
.
Метод ResultSet.insertRow
вставляет содержание строки вставки в ResultSet
возразите и в базу данных.
Отметьте: После вставки строки с ResultSet.insertRow
, следует переместить курсор в строку кроме строки вставки. Например, этот пример перемещает это в перед первой строкой в наборе результатов с методом ResultSet.beforeFirst
. Неожиданные результаты могут произойти, если другая часть Вашего приложения использует тот же самый набор результатов, и курсор все еще указывает на строку вставки.