Выбрать главу

Предположим, что есть написанное на Java приложение, которое неоднократно

выполняет один и тот же оператор INSERT, например, загружает

много новых товаров в наш гипотетический магазин. Для выполнения

этого процесса требуется добавить большое количество строк в таблицу

products при помощи 'операторов INSERT. Рассмотрим пример, реально

воплощающий это. Предположим, что класс Product был определен следующим

образом:

□ class Product {

int productld;

int productTypeld;

String name;

String description;

double price;

}

Следующий код создает массив из пяти объектов Product. Поскольку в

таблице products уже содержатся строки со значениями product_id от 1

до 12, атрибуты productld для новых объектов Product должны начинаться

с 13:

□ Product [ ] productArray = new Product [5];

for (in t counter = 0; counter < productArray.length; counter ++) {

productArray[counter] = new Product;

productArray[counter],productld = counter + 13;

productArray[counter],productTypeld = 1;

productArray[counter],name = “Test product” ;

productArray[counter].description = “Test product” ;

productArray[counter].price = 19.95;

} // конец цикла for

Для добавления строк в таблицу products используется цикл for, содержащий

оператор JDBC для выполнения оператора INSERT, а значения столбцов

будут взяты из массива productArray:

CJ Statement myStatement = myConnection.createStatement();

for (in t counter = 0; counter < productArray.length; counter ++) {

myStatement.executeUpdate(

582 Глава 15

“ INSERT INTO products “ +

“ (product_id, product_type_id, name, description, price) VALUES ( +

productArray[counter], productld + “ , “ +

productArray[counter]. product Type_Id + “ , ' ” +

productArray[counter],name + “ ’ , +

productArray[counter],description + “ +

productArrayfcounter],price + “ ) ”

);

} // конец цикла for

Каждое выполнение цикла (итерация) приводит к посылке в базу данных

оператора INSERT. Поскольку строки, представляющие каждый оператор

INSERT, содержат различные значения, реально посылаемый в базу данных

оператор INSERT каждый раз получается немного другим. Это означает,

что база данных создаст для каждого из них собственный план выполнения,

что, конечно, очень неэффективно.

JDBC предлагает более эффективный способ выполнения таких операторов

SQL. Вместо того чтобы для выполнения операторов SQL использовать

объект JDBC Statement, можно использовать для этой цели объект

PreparedStatement. Объект PreparedStatement позволяет выполнять один

и тот же оператор SQL, но при этом подставлять в него при выполнении

различные значения. Это более эффективно, так как при каждом выполнении

оператора SQL база данных использует один и тот же план выполнения.

В следующем примере создается объект PreparedStatement, содержащий

оператор INSERT, подобный оператору, рассмотренному в предыдущем

примере с циклом:

П PreparedStatement myPreparedStatement = myConnection.prepareStatement

(

“ INSERT INTO products “ +

“ ( product_id, product_type_id, name, description, price) VALUES ( +

“? ?, ?, ?, ?”

"г "

);

В этом примере следует обратить внимание на два момента.

■ Для задания оператора SQL используется метод prepareStatement().

■ Для указания позиций, куда впоследствии при реальном выполнении

оператора SQL будут подставлены значения переменных, используется

вопросительный знак (?).

Положение вопросительных знаков очень важно: к ним обращаются в

соответствии с их положением - к первому вопросительному знаку обращаются,

используя число 1, ко второму - 2 и т. д.

Процесс предоставления переменных Java в подготовленные операто

ры известен как привязка переменных к оператору, а предоставляемые

переменные - как переменные связи. Для реальной передачи переменных

в оператор следует применять методы установки (set). Эти методы похожи

на методы получения (get) (см. выше), но они используются для снабжения

переменных значениями, а не для считывания этих значений.

Выполнение SQL с использованием Java 583

Например, для привязки переменной типа int Java с именем intVar к

столбцу product_id в ранее созданном объекте PreparedStatement используется

SETInt(l, intVar). Первый параметр означает положение обрабатываемого

вопросительного знака в строке, указанной ранее в вызове метода

PrepareStatement(). Так, значение 1 соответствует первому вопросительному

знаку, снабжающему значением столбец product_id в операторе

INSERT. Для привязки переменной Java типа String с именем StringVar к

столбцу name используется вызов SETString(3, StringVar), так как третий

вопросительный знак соответствует столбцу name. К числу других методов,

которые можно вызывать в объекте PreparedStatement, относятся

SETFloat() и SETDouble() для установки чисел с плавающей точкой одинарной

и двойной точности.

В следующем примере показан цикл, демонстрирующий применение