Руководство по JDBC v.1
Предыдущий | Содержание | Следующий
6 - PreparedStatement
6.1 Введение
ИнтерфейсPreparedStatement наследует от Statement и отличается
от последнего следующим:
- Экземпляры
PreparedStatement"помнят" скомпилированные SQL-выражения. Именно поэтому они называются "prepared" ("подготовленные"). - SQL-выражения в
PreparedStatementмогут иметь один или более входной (IN) параметр. Входной параметр - это параметр, чье значение не указывается при создании SQL-выражения. Вместо него в выражении на месте каждого входного параметра ставится знак ("?"). Значение каждого вопросительного знака устанавливается методамиsetXXXперед выполнением запроса.
PreparedStatement прекомпилированны, исполнение этих запросов может
происходить несколько быстрее, чем в объектах Statement. В
результате SQL-выражения, которые исполняются часто, в целях улучшения
производительности создают в виде объектов PreparedStatement.
Оставаясь подклассом класса Statement, класс
PreparedStatement наследует все функции от Statement.
В дополнении к ним он добавляет методы установки входных параметров. Кроме того,
три метода - execute, executeQuery и
executeUpdate - модифицированы таким образом, что не имеют
аргументов. Старые методы класса Statement (которые принимают
SQL-выражения в качестве едиственного аргумента) не должны использоваться в
объекте PreparedStatement.
6.1.1 Создание объектов PreparedStatement
Следующий фрагмент кода, гдеcon - это объект
Connection, создает объект PreparedStatement,
содержащий SQL-выражение с двумя параметрами:
PreparedStatement pstmt = con.prepareStatement( "UPDATE table4 SET m = ? WHERE x = ?");Объект
pstmt отныне содержит выражение
"UPDATE table4 SET m = ? WHERE x = ?", которое уже отослано в СУБД
и подготовлено для выполнения.
6.1.2 Передача входных (IN) параметров
Перед выполнением объектаPreparedStatement надо
установить значения всех его параметров. Это делается с помощью методов
setXXX, где XXX - это тип параметра. Например, если
параметр имеет Java-тип long, используемый метод будет
setLong. Первый аргумент методов setXXX - это
порядковый номер параметра, а второй - значение, в которое надо его установить.
Например, следующий код устанавливает первый параметр в значение
123456789, а второй - в 100000000:
pstmt.setLong(1, 123456789); pstmt.setLong(2, 100000000);После установки параметра его можно использовать при многократном выполнении выражения до тех пор, пока он не очистится методом
clearParameters.
В режиме соединения по умолчанию (разрешена автофиксация) каждый запрос фиксируется или откатывается автоматически.
Один и тот же объект PreparedStatement может
выполняться много раз, если нижестоящий драйвер или СУБД будут сохранять
выражение (statement) в открытом состоянии даже после того как произойдет
фиксация. Иначе не имеет смысла пытаться улучшить производительность заменой
Statement на PreparedStatement.
Используя pstmt из предыдущего примера,
следующий код устанавливает значения обоих параметров и выполняет
pstmt 10 раз. Как уже было отмечено, БД не должна закрывать
pstmt. В этом примере первый параметр устанавливается в
"Hi" и остается неизменным. Второй параметр устанавливается в
последовательные целые значения, начиная от 0 и заканчивая 9.
pstmt.setString(1, "Hi");
for (int i = 0; i < 10; i++)
{
pstmt.setInt(2, i);
int rowCount = pstmt.executeUpdate();
}
6.1.3 Совместимость типов данных входных параметров
XXX в начвании методов setXXX - это
тип данных Java. Неявно он же является и типом данных JDBC (SQL), так как
драйвер отображает тип данных Java на соответствующий JDBC-тип (согласно таблице
из раздела 8.6.2)
перед отсылкой JDBC-типа в БД. Следующий код устанавливает второй параметр
объекта PreparedStatement pstmt в 44 с
типом данных short:
Драйвер отошлет 44 в БД в виде типа JDBCpstmt.setShort(2, 44);
SMALLINT, который является стандартным для Java-типа
short.
На программисте лежит ответственность за совместимость
Java-типов входных параметров и ожидаемых базой данных соответствующих
JDBC-типов. Рассмотрим случай, когда ожидается SMALLINT. Если
используется метод setByte, то драйвер отошлет значение
TINYINT в БД. Это, вероятно, работать будет, так как многие БД
преобразуют "похожие" типы данных друг в друга. Тем не менее, чтобы приложение
могдо работать как можно с большим количеством СУБД, лучше использовать
Java-типы, которые в точности соответствуют ожидаемым JDBC-типам. Если ожидается
JDBC-тип данных SMALLINT, то использование именно
setShort вместо setByte сделает приложение более
переносимым.
6.1.4 Использование объектов
Программист может явно задать конвертирование входных параметров в определенный JDBC-тип с помощью методаsetObject. Этот метод
может принимать третий аргумент, указывающий целевой JDBC-тип данных. Перед
отправкой в БД драйвер преобразует Object в указанный JDBC-тип.
Если JDBC-тип не задан, то драйвер просто преобразует
Object в его ближайший JDBC-эквивалент в соответствии с таблицей из
раздела 8.6.4,
а затем пошлет его в БД. Это подобно использованию обычных методов
setXXX; в обоих случаях драйвер отображает Java-типы в JDBC-типы
данных перед отправкой значений в БД. Разница заключается в том, что если методы
setXXX используют таблцу отображения Java-типов в JDBC-типы из
раздела 8.6.2),
то метод setObject использует отображение из таблицы в разделе 8.6.4.
В случае использования метода setObject тип
данных может быть неизвестен приложению на этапе его компиляции. Используя его,
приложение может подавать на вход значения любых типов данных и преобразовывать
их в ожидаемый базой данных JDBC-тип. Таблица из раздела 8.6.5
показывает все возможные преобразования, которые может проделать
setObject.
6.1.5 Отсылка значений NULL в качестве входного параметра
МетодsetNull позволяет отсылать
значения NULL в БД как входные параметры. Хотя JDBC-тип параметра
все же можно задать явно.
JDBC-значение NULL будет отослано в БД также в
том случае, если методу setXXX будет передано Java-значение
null (если метод принимает Java-объект в качестве аргумента). Тем
не менее, метод setObject может принять значение null
только в случае, если задан JDBC-тип.
6.1.6 Отправка очень больших входных параметров
МетодыsetBytes и setString могут
отсылать неограниченное количество данных. Правда, иногда программисту легче
передавать большие значения в виде маленьких кусков. Это делается установкой
входного параметра в значение Java-потока ввода (input stream). Когда
выполняется выражение, JDBC-драйвер будет производить последовательные вызовы из
этого потока ввода, считывая его содержимое и пересылая его в виде значения
параметра.
JDBC предоставляет три метода установки входных параметров
в поток ввода: setBinaryStream для потоков, содержащих обычные
байты, setAsciiStream для потоков ASCII-символов и
setUnicodeStream для потоков Unicode-символов. Эти методы, в
отличие от остальных методов setXXX, принимают дополнительный
аргумент, равный количеству передаваемых в потоке байтов. Этот аргумент
необходим, так как некоторые СУБД требуют указания размера данных перед их
отсылкой.
Следующий код иллюстрирует отсылку файла в виде входного параметра запроса:
java.io.File file = new java.io.File("/tmp/data");
int fileLength = file.length();
java.io.InputStream fin = new java.io.FileInputStream(file);
java.sql.PreparedStatement pstmt = con.prepareStatement(
"UPDATE Table5 SET stuff = ? WHERE index = 4");
pstmt.setBinaryStream (1, fin, fileLength);
pstmt.executeUpdate();При выполнении запроса для доставки данных
последовательно считывается поток ввода fin.
Предыдущий | Содержание | Следующий



Узнай о чем ты на самом деле сейчас думаешь

