|
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, это может означать одну из двух вещей: