Spec-Zone .ru
спецификации, руководства, описания, API
|
Эта страница затрагивает следующие темы:
Иногда более удобно использовать a PreparedStatement
объект для того, чтобы отправить SQL-операторы базе данных. Этот специальный тип оператора получается из более общего class, Statement
, то, что Вы уже знаете.
Если Вы хотите выполнить a Statement
возразите много раз, это обычно уменьшает время выполнения, чтобы использовать a PreparedStatement
объект вместо этого.
Основная функция a PreparedStatement
объект - это, в отличие от a Statement
объект, этому дают SQL-оператор, когда это создается. Преимущество для этого состоит в том, что в большинстве случаев, этот SQL-оператор отправляется DBMS сразу же, где это компилируется. В результате PreparedStatement
объект содержит не только SQL-оператор, но и SQL-оператор, который был предварительно скомпилирован. Это означает это когда PreparedStatement
выполняется, DBMS может только работать PreparedStatement
SQL-оператор, не имея необходимость компилировать это сначала.
Хотя PreparedStatement
объекты могут использоваться для SQL-операторов без параметров, Вы, вероятно, используете их чаще всего для SQL-операторов, которые берут параметры. Преимущество использования SQL-операторов, которые берут параметры, состоит в том, что можно использовать тот же самый оператор и предоставить его различные значения каждый раз, когда Вы выполняете его. Примеры этого находятся в следующих разделах.
Следующий метод, CoffeesTable.updateCoffeeSales
, хранит число фунтов кофе, проданного на текущей неделе в SALES
столбец для каждого типа кофе, и обновления общее количество фунтов кофе, проданного в TOTAL
столбец для каждого типа кофе:
public void updateCoffeeSales(HashMap<String, Integer> salesForWeek) throws SQLException { PreparedStatement updateSales = null; PreparedStatement updateTotal = null; String updateString = "update " + dbName + ".COFFEES " + "set SALES = ? where COF_NAME = ?"; String updateStatement = "update " + dbName + ".COFFEES " + "set TOTAL = TOTAL + ? " + "where COF_NAME = ?"; try { con.setAutoCommit(false); updateSales = con.prepareStatement(updateString); updateTotal = con.prepareStatement(updateStatement); for (Map.Entry<String, Integer> e : salesForWeek.entrySet()) { updateSales.setInt(1, e.getValue().intValue()); updateSales.setString(2, e.getKey()); updateSales.executeUpdate(); updateTotal.setInt(1, e.getValue().intValue()); updateTotal.setString(2, e.getKey()); updateTotal.executeUpdate(); con.commit(); } } catch (SQLException e ) { JDBCTutorialUtilities.printSQLException(e); if (con != null) { try { System.err.print("Transaction is being rolled back"); con.rollback(); } catch(SQLException excep) { JDBCTutorialUtilities.printSQLException(excep); } } } finally { if (updateSales != null) { updateSales.close(); } if (updateTotal != null) { updateTotal.close(); } con.setAutoCommit(true); } }
Следующее создает a PreparedStatement
объект, который берет два входных параметра:
String updateString = "update " + dbName + ".COFFEES " + "set SALES = ? where COF_NAME = ?"; updateSales = con.prepareStatement(updateString);
Следует предоставить значения вместо заполнителей вопросительного знака (если есть кто-либо) прежде, чем можно будет выполнить a PreparedStatement
объект. Сделайте это, вызывая один из методов метода set, определенных в PreparedStatement
class. Следующие операторы предоставляют двух заполнителей вопросительного знака в PreparedStatement
именованный updateSales
:
updateSales.setInt(1, e.getValue().intValue()); updateSales.setString(2, e.getKey());
Первый параметр за каждый из этих методов метода set определяет заполнителя вопросительного знака. В этом примере, setInt
определяет первого заполнителя и setString
определяет второго заполнителя.
После того, как параметры были установлены со значением, они сохраняют то значение, пока они не сбрасываются к другому значению, или методу clearParameters
вызывается. Используя PreparedStatement
объект updateSales
, следующий фрагмент кода иллюстрирует многократное использование готового оператора после сброса значения одного из его параметров и отъезда другого то же самое:
// changes SALES column of French Roast //row to 100 updateSales.setInt(1, 100); updateSales.setString(2, "French_Roast"); updateSales.executeUpdate(); // changes SALES column of Espresso row to 100 // (the first parameter stayed 100, and the second // parameter was reset to "Espresso") updateSales.setString(2, "Espresso"); updateSales.executeUpdate();
Можно часто делать кодирование легче при использовании a for
цикл или a while
цикл, чтобы установить значения для входных параметров.
CoffeesTable.updateCoffeeSales
метод использует цикл foreach, чтобы неоднократно установить значения в PreparedStatement
объекты updateSales
и updateTotal
:
for (Map.Entry<String, Integer> e : salesForWeek.entrySet()) { updateSales.setInt(1, e.getValue().intValue()); updateSales.setString(2, e.getKey()); // ... }
Метод CoffeesTable.updateCoffeeSales
берет один параметр, HashMap
. Каждый элемент в HashMap
параметр содержит имя одного типа кофе и числа фунтов того типа кофе, проданного в течение текущей недели. Цикл foreach выполняет итерации через каждый элемент HashMap
параметр и наборы соответствующие заполнители вопросительного знака в updateSales
и updateTotal
.
Как с Statement
объекты, чтобы выполнить a PreparedStatement
объект, вызовите выполнить оператор: executeQuery
если запрос возвращает только один ResultSet
(такие как a SELECT
SQL-оператор), executeUpdate
если запрос не возвращает a ResultSet
(такой как UPDATE
SQL-оператор), или execute
если запрос мог бы возвратить больше чем один ResultSet
объект. Оба PreparedStatement
объекты в CoffeesTable.updateCoffeeSales
содержать UPDATE
SQL-операторы, таким образом, оба выполняются, вызывая executeUpdate
:
updateSales.setInt(1, e.getValue().intValue());
updateSales.setString(2, e.getKey());
updateSales.executeUpdate();
updateTotal.setInt(1, e.getValue().intValue());
updateTotal.setString(2, e.getKey());
updateTotal.executeUpdate();
con.commit();
Никакие параметры не предоставляются executeUpdate
когда они используются, чтобы выполниться updateSales
и updateTotals
; оба PreparedStatement
объекты уже содержат SQL-оператор, который будет выполняться.
Отметьте: В начале CoffeesTable.updateCoffeeSales
, режим автоматической фиксации устанавливается в ложь:
con.setAutoCommit(false);
Следовательно, никакие SQL-операторы фиксируются до метода commit
вызывается. Для получения дополнительной информации о режиме автоматической фиксации, см. Транзакции.
Принимая во внимание, что executeQuery
возвраты a ResultSet
объект, содержащий результаты запроса, отправленного DBMS, возвращаемому значению для executeUpdate
int
значение, которое указывает, сколько строк таблицы было обновлено. Например, следующий код показывает возвращаемое значение executeUpdate
будучи присвоенным переменной n
:
updateSales.setInt(1, 50); updateSales.setString(2, "Espresso"); int n = updateSales.executeUpdate(); // n = 1 because one row had a change in it
Таблица COFFEES
обновляется; значение 50 замен значение в столбце SALES
в строке для Espresso
. То обновление влияет на одну строку в таблице, таким образом, n
равно 1.
Когда метод executeUpdate
используется, чтобы выполнить DDL (язык определения данных) оператор, такой как в составлении таблицы, это возвращается int
значение 0. Следовательно, в следующем фрагменте кода, который выполняет оператор DDL, используемый, чтобы составить таблицу COFFEES
, n
присваивается значение 0:
// n = 0 int n = executeUpdate(createTableCoffees);
Отметьте что когда возвращаемое значение для executeUpdate
0, это может означать одну из двух вещей: