что такое statement preparedstatement callablestatement
Класс Statement
Statement используется для выполнения SQL-запросов. Существует три типа класса Statement, которые являются как бы контейнерами для выполнения SQL-выражений через установленное соединение:
Все классы специализируются для выполнения различных типов запросов:
Создание объектов Statement
После установления соединения Connection с базой данных, оно может использоваться для выполнения SQL-запросов. Объект Statement создается методом Connection.createStatement.
Пример :
Для отправки серверу БД SQL-выражения для выполнения необходимо вызвать метод executeQuery объекта Statement и в качестве аргумента передать скрипт запроса :
Методы Statement : executeQuery, executeUpdate, execute
Класс Statement содержит три различных метода выполнения SQL-выражений : executeQuery, executeUpdate и execute, которые вызываются в зависимости от текста SQL-запроса.
executeQuery
Метод executeQuery используется в запросах, результатом которых является один единственный набор значений, таких как запросов типа SELECT.
executeUpdate
Результатом выполнения операторов INSERT, UPDATE, или DELETE является изменения одной или более строк таблицы.
Результатом выполнения метода executeUpdate является целочисленное значение, определяющее, сколько строк было модифицировано. Для выражений DML, которые не оперируют со строками, возвращаемое методом executeUpdate значение всегда равно нулю.
execute
Метод execute используется, когда операторы SQL возвращают более одного набора данных, более одного счетчика обновлений или и то, и другое. Такая возможность редко используется программистами.
Объекты Statement сами по себе не «помнят» SQL-выражение. Оно передается в качестве аргумента методов Statement.executeXXX.
Необходимо отметить, что PreparedStatement, наследующий все методы Statement, имеет свои реализации методов executeQuery, executeUpdate и execute. Объекты PreparedStatement не принимают SQL-выражения в виде аргументов этих методов, так как они уже содержат прекомпилированные SQL-выражения.
CallableStatement наследуют методы от PreparedStatement без параметров. Использование аргументов в методах executeXXX объектов PreparedStatement и CallableStatement приведет к генерации ошибки SQLException.
Объекты Statement закрываются автоматически сборщиком мусора виртуальной машины Java. Тем не менее рекомендуется закрывать их явно после того, как работа с ними завершена. Закрытие объектов Statement после их использования освобождает ресурсы СУБД и позволяет избежать проблем с памятью.
Завершение выполнения запросов
Объект Statement считается завершенным (complete), если он выполнился и все его результаты были возвращены.
Для метода executeQuery, возвращающий набор данных, оператор считается завершенным, если считаны все строки соответствующего объекта ResultSet. В случае использования метода executeUpdate объект завершен сразу же после выполнения метода.
В случае вызова метода execute оператор остается не завершенным до тех пор, пока все наборы данных не будут считаны.
Использование PreparedStatement
PreparedStatement предварительно компилирует запросы, которые могут содержать входные параметры обозначенные символом ‘?’
Пример использования PreparedStatement
Использование CallableStatement
Синтаксис вызова хранимой процедуры в JDBC показан ниже. Квадратные скобки означают, что то, что находится между ними, необязательно, и сами по себе не являются частью синтаксиса.
Первые две формы могут иметь переменное число аргументов на входе (параметры IN), выходе (параметры OUT) или входных и выходных параметров одновременно (INOUT-параметры). Вопросительный знак означает местоположение параметра.
Метод supportsStoredProcedures() класса DatabaseMetaData позволяет узнать, поддерживает СУБД хранимые процедуры или нет.
Создание объекта CallableStatement
Объекты CallableStatement создаются методом prepareCall объекта Connection. Пример, который создает экземпляр CallableStatement, содержащий вызов хранимой процедуры setGoodsData с двумя аргументами и без возвращаемого параметра:
Входные и выходные IN- и OUT-параметры
Передача значений входных парметров объекта CallableStatement осуществляется с помощью методов setXXX, унаследованных от PreparedStatement. Типы передаваемых значений определяются тем, какой из методов setXXX используется (setString для передачи значений типа String, setInt для передачи значений типа int и т.п.).
JDBC-типы всех OUT-параметров хранимых процедур должны быть зарегистрирваны перед их вызовом. Регистрация типов данных выходного параметра производится методом registerOutParameter. Только в этом случае после вызова хранимой процедуры CallableStatement.executeQuery() можно получить результаты выполнения с помощью методов getXXX. Необходимо использовать подходящий по типу данных Java метод getXXX в соответствии с зарегистрированным JDBC-типом параметра. Другими словами, registerOutParameter использует JDBC-тип, который подходит к JDBC-типу возвращаемого из значения, а getXXX преобразует его в тип Java.
Пример регистрации выходных параметров хранимой процедуры и чтение выходных значений. В примере метод getByte извлекает байт из первого выходного параметра, а getBigDecimal возвращает объект BigDecimal (с двумя цифрами после десятичной точки) из второго выходного параметра :
Чтение выходных параметров
В связи с ограничениями некоторых СУБД для большей совместимости рекомендуется сначала считывать результаты, сгенерированные вызовом CallableStatement, а затем выходные (OUT) параметры.
Если объект CallableStatement возвращает несколько объектов ResultSet (с использованием метода execute), то ВСЕ результаты должны быть прочитаны перед первым обращением к выходным параметрам. В этом случае для того, чтобы прочитать все результаты, надо последовательно вызывать методы Statement getResultSet, getUpdateCount и getMoreResults до тех пор, пока не останется больше результатов. После этого значения выходных параметров могут быть извлечены спомощью методов CallableStatement.getXXX.
Нулевое значение в выходных параметрах, wasNull
Возращаемое значение в выходном параметре может быть NULL. При этом методы getXXX возвращают null, 0 или false, в зависимости от типа данных.
Как и в случае с ResultSet, единственным способом узнать, вернула ли процедура 0, false или NULL, является вызов метода wasNull, который возвращает true, если последнее значение, считанное одним из методов getXXX был NULL, и false иначе.
Входные/выходные параметры INOUT
Если параметр является одновременно и входным, и выходным (INOUT), то необходимо вызывать как метод setXXX, так и метод registerOutParameter. Метод setXXX устанавливает входное значение параметра, а registerOutParameter регистрирует тип выходного значения.
Типы входного и выходного значений, зарегистрированных методом registerOutParameter, должны быть одинаковыми. Для чтения выходного значения используется соответствующий метод getXXX. Например, для параметра типа byte нужно использовать метод установки значения setByte, передавать JDBC-тип данных TINYINT методу registerOutParameter и использовать getByte для чтения выходного значения.
В следующий пример демонстрирует вызов хранимой процедуры rebuildTotal с одним INOUT-параметром. Метод setByte устанавливает значение параметра в 25, которое будет передано хранимой процедуре базе данных как TINYINT. Далее метод registerOutParameter регистрирует 1-ый параметр как TINYINT. После выполнения хранимой процедуры возвращается значение типа TINYINT, которое будет считано методом getByte в виде типа byte языка Java.
Если хранимая процедура оформлена функцией, т.е возвращает значение не через параметры, а через оператор «RETURNS», то для вызова используйте «execute» вместо «executeUpdate».
В отличие от ResultSet, CallableStatement не может считывать большие значения последовательно (в потоке)..
Escape-последовательности в запросах Statement
SQL-выражения Statement‘ов могут включать escape-последовательности, которые сигнализирует о том, что код выражения должен обрабатываться особо. Escape-последовательности заменяются кодом, специфичным для данной СУБД. Escape-синтаксис независит от типа СУБД
Cинтаксис escape-последовательности
Escape-конструкция заключается в фигурные скобки, где определяется ключевое слово и параметры :
Ключевое слово индицирует вид Escape-конструкции.
1. escape-последовательность с символом
Операция SQL типа LIKE использует шаблонные символы «%» и «_», которые используются для извлечения информации с определенными символами. Чтобы эти символы интерпретировались в SQL-выражении без изменений, необходимо перед ними установить обратный символ слэша «\». Этот специальный символ и называется escape-символом.
Можно явно определить, какой именно из символов использовать в качестве escape-символа, если в конце запроса ввести следующую конструкцию:
В следующем коде осуществляется чтение строки, начинающейся со знака подчеркивания:
2. escape-последовательность с функциией fn
Практически во всех СУБД есть функции для манипуляции с числами, строками, временем, датой. Эти функции могут использоваться в escape-конструкции с ключевым словом fn, именем функции и ее аргументами. Следующий пример вызывает функцию конкатенации concat с двумя аргументами:
Имя текущего пользователя БД может быть извлечено с помощью следующего вызова:
Скалярные функции могут поддерживаться различными СУБД с немного отличающимся синтаксисом, а некоторыми СУБД могут и не поддерживаться вовсе.
Для получения списка поддерживаемых СУБД функций можно использовать класс чтения метаданных DatabaseMetaData, у которого метод getNumericFunctions возвращает список имен числовых функций, разделенных запятой, а метод getStringFunctions возвращает строковые функции, и т.д.
3. escape-последовательность для работы с датой и временам
Различные СУБД отличаются форматом записи и чтения даты, времени и временного штампа, включающего дату и время (timestamp).
Формат использование escape-последовательности даты следующий:
Аналогичным образом обрабатываются escape-конструкции для типов данных TIME и TIMESTAMP:
Милисекунда (.ms) в TIMESTAMP может быть опущена.
4. escape-последовательность с хранимыми процедурами
Для обращения к хранимой процедуры из JDBC используется либо call, либо ? = call.
Если СУБД поддерживает хранимые процедуры, то они могут вызываться из JDBC с помощью следующего синтаксиса escape-последовательности:
Пакетная обработка в JDBC и HIBERNATE
В этой статье, я кратко расскажу о пакетной обработке SQL (DML) операторов: INSERT, UPDATE, DELETE, как одной из возможностей достижения увеличения производительности.
Преимущества
В отличие от последовательного выполнения каждого SQL запроса, пакетная обработка даёт возможность отправить целый набор запросов (пакет) за один вызов, тем самым уменьшая количество требуемых сетевых подключений и позволяя БД выполнять какое-то количество запросов параллельно, что может значительно увеличить скорость выполнения. Сразу оговорюсь, что заметный эффект можно увидеть при вставке, обновлении или удалении больших объёмов данных в таблицу БД.
Таблица БД
В качестве примера будет использована таблица book c полями id и title.
id | title |
---|---|
10001 | Java Persistence API и Hibernate |
10002 | Новая большая книга CSS |
10003 | Spring 5 для профессионалов |
10004 | Java ЭФФЕКТИВНОЕ ПРОГРАММИРОВАНИЕ |
1. JDBC — пакетная обработка
Прежде чем перейти к примерам реализации, необходимо осветить несколько важных моментов:
Далее, я приведу небольшие примеры использования интерфейсов Statement, PreparedStatement и CallableStatement в пакетной обработке. В примерах размер пакета указывается, как BATCH_SIZE. Значение размера пакета должно быть оптимальное, то есть не слишком большое, но и не слишком маленькое (например, 10-50).
В примерах, я ограничусь и буду использовать SQL оператор INSERT. Для UPDATE, DELETE всё аналогично.
1.1. Интерфейс Statement
Пример использования Statement для добавления данных пакетами в таблицу book.
Использование объекта Statement даёт возможность собирать в один пакет разные SQL операторы INSERT, UPDATE, DELETE.
Каждый SQL запрос проверяется и компилируется БД, что приводит к увеличению времени выполнения.
1.2. Интерфейс PreparedStatement
Пример использования PreparedStatement для добавления данных пакетами в таблицу book.
Шаги 3) и 4) такие же, как и для Statement, единственное отличие — это addBatch() без параметров.
SQL запрос компилируется и оптимизируется базой данных один раз, после чего его можно использовать многократно, задавая различные значения параметров. И это серьёзное преимущество, так как не затрачивается время на компиляцию каждого последующего запроса.
1.3. Интерфейс CallableStatement
Интерфейс CallableStatement используется для выполнения хранимых на сервере БД процедур.
Пакетная обработка предусматривает исполнение хранимых процедур при условии, что процедуры не содержат параметров OUT или INOUT.
Пример использования CallableStatement для добавления данных пакетами в таблицу book.
Не затрачивается время на компиляцию, так как хранимая процедура компилируется один раз при первом ее запуске, а затем сохраняется в скомпилированной форме на сервере БД.
Хранимые процедуры предоставляют возможность производить какие-либо вычисления перед тем как совершить манипуляцию с данными, выполнять сложную транзакционную логику.
Использование интерфейса CallableStatement не предусматривает возможности собирать в один пакет вызовы разных хранимых процедур, а только какой-то одной.
1.4. Класс BatchUpdateException
Небольшой демонстрационный пример:
Этот пример показывает лишь суть выше изложенного. В реальной же ситуации необходимо логировать сам запрос, который привёл к ошибке, так как сам по себе индекс малоинформативен, а для этого необходимо предусмотреть в обработчике сохранение пакета запросов перед их выполнением, чтоб в случае получения исключения уже по индексу определить запросы повлёкшие к нему. К сожалению объект BatchUpdateException не содержит методов получения SQL запросов, которые содержались в пакете и привели к исключению. Поэтому полная реализация механизма логирования и обработки ложиться на плечи разработчика.
2. Hibernate — пакетная обработка
2.1. Изменения в конфигурационном файле
2.2. Примеры реализации пакетной обработки
Прежде чем перейти к примерам реализации обратим внимание на некоторые аспекты связанные с контекстом хранения. Как известно, контекст хранения служит кэшем хранимых экземпляров. При попытке загрузить тысячи экземпляров сущностей, Hibernate сделает копию каждого экземпляра в кэше контекста хранения, что может привести к исчерпанию памяти OutOfMemoryException. Есть 2 варианта предотвращения полного расходования памяти:
2.3. Сбор статистики
Для того чтобы убедиться, что Hibernate действительно использует пакетную обработку, можно временно включить сбор статистики. Для этого необходимо в конфигурационном файле Hibernate.cfg.xml установить свойство «hibernate.generate_statistics» в true.
При пакетной вставке, удалении, обновлении статистика будет содержать информацию о затраченном времени и количестве выполненных пакетов.
Пример информации из статистики.
Вывод
Пакетное выполнение SQL запросов – это один из известных способов повышения производительности на который стоит обратить внимание. Уменьшение количества сетевых подключений к БД и увеличение скорости выполнения запросов является существенным плюсом в пользу использования пакетной обработки.
Что такое statement preparedstatement callablestatement
Изучение интерфейсов Statement, PrepareStatement и CallableStatement.
Интерфейсы Statement, PrepareStatement и CallableStatement определяют методы и свойства, позволяющие выдавать запросы и команды в базу данных, а также получать результаты выполнения запросов. Они также предусматривают методы, упрощающие процедуру преобразования типов данных JAVA-SQL. В качестве примера можно привести тип данных integer. В java данные типа integer не могут принимать значение NULL. В базе данных напротив пустые значения любых типов представляются NULL значением.
Первым в иерархии стоит интерфейс Statement. Интерфейс PrepareStatement расширяет интерфейс Statement. Интерфейс CallableStatement в свою очередь расширяет интерфейс PrepareStatement. Производители JDBC драйверов применяют перечисленные выше интерфейсы в классах поставляемых ими драйверов и реализуют соответствующие методы. Таким образом, без регистрации конкретного драйвера невозможно создать объект с использованием перечисленных выше интерфейсов.
Statement интерфейс используют в случае выполнения статических запросов к базе данных. Такие запросы не могут содержать изменяемые параметры.
PrepareStatemet интерфейс используют в случае многократного выполнения одного и того же запроса с динамически меняющимися параметрами.
CallableStatement интерфейс используется для доступа к хранимым в базе данных процедурам. Этот интерфейс тоже может использоваться с динамически изменяемыми параметрами.
Объекты, созданные с использованием данных интерфейсов, имею четыре основных метода для выполнения запросов к базе данных:
Для использования этих методов прежде всего необходимо создать сам объект типа Statement методом createStatement() объекта типа Connection. Метод executeQuery(), равно как и шаги, предшествующие его выполнению, подробно рассмотрены в материалах к занятию №1. Ниже приведен пример использования метода executeUpdate() для дополнения учебной базы данных двумя таблицами и заполнения их небольшим количеством демонстрационных данных.
//Занятие 2, пример 2-1
public static void createTables() throws SQLException <
String operatorsql = «CREATE TABLE операторы_связи «
+ «(ид NUMBER(3) CONSTRAINT ПК_ОС PRIMARY KEY,»
String telefonsql = «CREATE TABLE номера_телефонов «
+ «(ид_л NUMBER(9) CONSTRAINT ВК_Л REFERENCES н_люди(ид),»
+ «ид_ос NUMBER(3) CONSTRAINT ВК_ОС REFERENCES операторы_связи(ид))» ;
st.executeUpdate( «DROP TABLE операторы_связи CASCADE CONSTRAINTS» );
> catch (SQLException se) <
//Игнорировать ошибку удаления таблицы
String msg = se.getMessage();
System.out.println( «Ошибка при удалении таблицы: » +msg);
//Создание таблицы операторы_связи
System.out.println( «Таблица операторы_связи создана. » );
st.executeUpdate( «DROP TABLE номера_телефонов» );
> catch (SQLException se) <
//Игнорировать ошибку удаления таблицы
String msg = se.getMessage();
System.out.println( «Ошибка при удалении таблицы: » +msg);
//Создание таблицы номера_телефонов
System.out.println( «Таблица номера_телефонов создана. » );
public static void insertData() throws SQLException <
//Загрузка данных в таблицу операторы_связи
st.executeUpdate(«INSERT INTO операторы_связи VALUES(1,’Мегафон’)»);
st.executeUpdate(«INSERT INTO операторы_связи VALUES(2,’МТС’)»);
st.executeUpdate(«INSERT INTO операторы_связи VALUES(3,’Би Лайн’)»);
st.executeUpdate(«INSERT INTO операторы_связи VALUES(4,’SkyLink’)»);
//Загрузка данных в таблицу номера_телефонов
st.executeUpdate(«INSERT INTO номера_телефонов VALUES(125704,’9363636′,
st.executeUpdate(«INSERT INTO номера_телефонов VALUES(125704,’2313131′,
st.executeUpdate(«INSERT INTO номера_телефонов VALUES(125704,’1151515′,
st.executeUpdate(«INSERT INTO номера_телефонов VALUES(120848,’4454545′,
st.executeUpdate(«INSERT INTO номера_телефонов VALUES(120848,’1161616′,
System.out.println(«Загрузка данных закончена. «);
Для изучения примера необходимо создать класс, использующий main метод для регистрации драйвера, создания соединения с базой данных, создания объекта типа Statement и обработки соответствующих исключений. Для создания таблиц и заполнения их данными необходимо использовать отдельные методы (аналогичные приведенным в примере).
При заполнении таблицы номера_телефонов данные о дате регистрации телефона указываются с использованием JDBC SQL escape последовательности, которая имеет следующий формат: <ключевое_слово параметр>. В данном примере ключевым словом является символ d, который сообщает драйверу о необходимости преобразования указанной в качестве параметра даты в формат даты ORACLE.
Statement st = conn.createStatement();
st.execute( любой SQL-запрос );
//Вывести результат запроса
//Вывести количество обработанных строк
Для изучения этого метода необходимо создать класс, в методе main которого выполнить следующий фрагмент кода:
//Занятие 2, пример 2-2
Connection conn = null;
Statement st = null;
ResultSet rs = null;
//Начало блока обработки исключений (try)
//Регистрация драйвера, и создание соединения
String sql = «INSERT INTO номера_телефонов VALUES(121018,’9999999′,
sql = «SELECT фамилия, имя, номер_телефона, дата_регистрации, оператор «
+»FROM н_люди л, номера_телефонов т, операторы_связи о «
+»WHERE л.ид = т.ид_л AND т.ид_ос = о.ид»;
>//Блок обработки исключений (catch, finally)
Обработку результатов, полученных методом execute() реализовать отдельным метод:
public static void processExecute(Statement st,
boolean executeResult) throws SQLException <
//Код обработки результатов
>//end of processExecute metod
Использование метода executeBatch() тесно связано с использованием технологии транзакций. Этот метод позволяет выполнить за одно обращение к базе данных группу заранее подготовленных запросов. В случае неудачи выполнения одного из запросов можно отменить (откатить) все изменения, сделанные данной группой запросов с помощью метода rollback(). Ниже приведен фрагмент программного кода, иллюстрирующий данную возможность:
//Занятие 2, пример 2-3
public static void batchInsert() throws SQLException <
//Загрузка данных в таблицу операторы_связи
st.addBatch(«INSERT INTO операторы_связи VALUES(1,’Мегафон’)»);
st.addBatch(«INSERT INTO операторы_связи VALUES(2,’МТС’)»);
st.addBatch(«INSERT INTO операторы_связи VALUES(3,’Би Лайн’)»);
st.addBatch(«INSERT INTO операторы_связи VALUES(4,’SkyLink’)»);
//Загрузка данных в таблицу номера_телефонов
st.addBatch(«INSERT INTO номера_телефонов VALUES(125704,’9363636′,
st.addBatch(«INSERT INTO номера_телефонов VALUES(125704,’2313131′,
st.addBatch(«INSERT INTO номера_телефонов VALUES(125704,’1151515′,
st.addBatch(«INSERT INTO номера_телефонов VALUES(120848,’4454545′,
st.addBatch(«INSERT INTO номера_телефонов VALUES(120848,’1161616′,
System.out.println(«Пакет загрузки данных подготовлен. «);
int[] count = st.executeBatch();
Формирование пакета запросов осуществляется методом addBatch() с параметром типа String. При необходимости, для аннулирования уже сформированного пакета запросов можно использовать метод clearBatch(). В этом случае весь пакет будет аннулирован и его можно начать формировать заново. Перед выполнением пакета для использования режима транзакций необходимо отменить автоматическое подтверждение изменений в результате выполнения каждого запроса, то есть выполнить метод setAutoCommit(false). После выполнения метода executeBatch() необходимо выполнить метод commit() для подтверждения сделанных в базе изменений. В случае неудачного выполнения одного из запросов будет получено исключение типа SQLException. В блоке обработки исключения можно использовать метод rollback() для отмены (отката) сделанных в базе данных изменений. Для изучения перечисленных выше методов необходимо в созданном для примера 2-1 классе заменить метод insertDate() на метод batchInsert() данного примера и выполнить его.
Для более гибкого управления ходом выполнения транзакций существует возможность установки логических точек отката изменений, сделанных в базе в процессе выполнения последовательности транзакций. Для этого используется метод setSavepoint(String Имя точки отката ). Для аннулирования ранее установленной точки отката можно использовать метод releaseSavepoint(Savepoint svpt). В случае возникновения исключения при выполнении транзакции можно либо отменить все начатые изменения в базе данных с момента последнего выполнения метода setAutoCommit(false), либо отменить их до установленной логической точки отката методом rollback(Savepoint svpt). Ниже приведен фрагмент программного кода, на примере которого необжодимо изучить данную возможность, дополнив его до полноценного класса.
//Занятие 2, пример 2-4
public class RollBackMethod <
public static void main(String[] args) <
//Регистрация драйвера, и создание соединения
if(!conn.getAutoCommit()) System.out.println(«Auto-Commit отменен. «);
String sql = «INSERT INTO операторы_связи VALUES(5,’TELE2′)»;
sql = «INSERT INTO номера_телефонов VALUES(130777,’2223322′,
> catch (SQLException se) <
System.out.println(«SQLException сообщение: «+se.getMessage());
System.out.println(«Начнем откат изменений. «);
> catch (SQLException rse) <
System.out.println(«Откат изменений закончен. «);
> catch (SQLException se) <
Существует три типа параметров: IN, OUT и INOUT. Объекты типа PreparedStatemet используют только параметры типа IN. Перед выполнением запроса необходимо установить все параметры методом setXXX(), где XXX заменяется на соответствующее типу данных параметра ключевое слово, например: setInt(), setString(), setDate(), setTime(). Если какой либо из параметров не установлен, то будет выдано исключение типа SQLEception. При установке параметра указывается его номер по порядку, начиная с 1, как он встречается в SQL-предложении, и его значение. Посла выполнения подготовленного таким образом запроса установленные параметры не сбрасываются. Их можно сбросить методом clearParameters() или переустановить упомянутыми выше методами setXXX().
В случае использования метода executeBatch() после каждого утановки каждого полного комплекта параметров выполняется метод addBatch() без аргументов.
Для изучения интерфейса PrepareStatemet и применения его методов необходимо выполнить приведенный ниже пример, дополнив его реализацией необходимых методов:
//Занятие 2, пример 2-5
public class PrepStatDB <
static Connection conn = null;
public static void main(String[] args) <
//Регистрация драйвера, и создание соединения
System.out.println(«Создание базы данных закончено. «);
> catch (SQLException se) <
> catch (SQLException se) <
public static void createTables() throws SQLException <
Statement st = conn.createStatement();
//Программный код создания таблиц базы данных (см. пример 1-1)
public static void insertData() throws SQLException <
//Загрузка данных в таблицу операторы_связи
String sql = «INSERT INTO операторы_связи VALUES(. )»;
PreparedStatement prst = conn.prepareStatement(sql);
prst.setInt(1,1); prst.setString(2,»Мегафон»); count = prst.executeUpdate();
System.out.println(«Запись \»Мегафон\» добавлена»);
prst.setInt(1,2); prst.setString(2,»МТС»); count = prst.executeUpdate();
System.out.println(«Запись \»МТС\» добавлена»);
prst.setInt(1,3); prst.setString(2,»Би Лайн»); count = prst.executeUpdate();
System.out.println(«Запись \»Би Лайн\» добавлена»);
prst.setInt(1,4); prst.setString(2,»SkyLink»); count = prst.executeUpdate();
System.out.println(«Запись \»SkyLink\» добавлена»);
//Загрузка данных в таблицу номера_телефонов
sql = «INSERT INTO номера_телефонов VALUES(. )»;
prst.setInt(1,125704); prst.setString(2,»9363636″); prst.setDate(3,Date.valueOf(«2000-9-15»)); prst.setInt(4,1); prst.addBatch();
prst.setInt(1,125704); prst.setString(2,»2313131″); prst.setDate(3,Date.valueOf(«2001-2-25»)); prst.setInt(4,2); prst.addBatch();
prst.setInt(1,125704); prst.setString(2,»1151515″); prst.setDate(3,Date.valueOf(«2002-6-17»)); prst.setInt(4,4); prst.addBatch();
prst.setInt(1,120848); prst.setString(2,»4454545″); prst.setDate(3,Date.valueOf(«2003-7-30»)); prst.setInt(4,3); prst.addBatch();
prst.setInt(1,120848); prst.setString(2,»1161616″); prst.setDate(3,Date.valueOf(«2004-1-16»)); prst.setInt(4,4); prst.addBatch();
int[] countb = prst.executeBatch();
System.out.println(«\n»+»Загрузка данных закончена. «);
При работе с данными типа CLOB и BLOB значения параметров можно задавать и получать используя потоки ввода и вывода. При этом используются следующие методы:
В качестве параметров методам setXXXStream() указывается номер по порядку, объект типа InputStream и длина объекта. Получение потока данных производится методами getXXXStream(). Ниже приведен пример записи ASCII файла в поле предварительно созданной таблицы readme.
//Занятие 2, пример 2-6
public class StreamMethod <
public static void main(String[] args) <
Connection conn = null;
Statement st = null;
PreparedStatement prst = null;
ResultSet rs = null;
//Регистрация драйвера, и создание соединения
File f = new File(«/etc/passwd»);
long fileLength = f.length();
FileInputStream fis = new FileInputStream(f);
String sql = «INSERT INTO readme VALUES(. )»;
sql = «SELECT * FROM readme WHERE >
InputStream is = rs.getAsciiStream(2);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
> catch (SQLException se) <
> catch (SQLException se) <
public static void createReadmeTable(Statement st) throws Exception <
String sql = «CREATE TABLE readme (id INTEGER, data LONG)»;
st.executeUpdate(«DROP TABLE readme»);
> catch (SQLException se) <
//Игнорировать ошибку удаления таблицы
String msg = se.getMessage();
System.out.println(«Ошибка при удалении таблицы: «+msg);
System.out.println(«Таблица readme создана. «);
Объекты типа CallableStatement создается методом prepareCall() объекта типа Connection и позволяют выполнять хранимые в базе данных процедуры. При этом могу использоваться параметры всех трех типов: IN, OUT и INOUT. SQL-предложение при этом подготавливается в виде JDBC SQL escape последовательности:
call ключевое слово escape-последовательности;
proc_name имя хранимой процедуры;
Ниже приведен пример создания хранимой процедуры, использующей функцию человек учебной базы данных, которая по номеру сотрудника выдает его фамилию и инициалы.
//Занятие 2, пример 2-7
public static void createProc() throws SQLException <
Statement st = conn.createStatement();
String sql = «CREATE PROCEDURE get_fio «
+»(id IN NUMBER, fio OUT VARCHAR) AS «
+»SELECT человек(id, ‘И’, 9) INTO fio FROM DUAL; «
st.executeUpdate(«DROP PROCEDURE get_fio»);
> catch (SQLException se) <
//Игнорировать ошибку удаления процедуры
String msg = se.getMessage();
System.out.println(«Ошибка при удалении процедуры: «+msg);
System.out.println(«Процедура get_fio создана. «);
public static void executeProc() throws SQLException <
CallableStatement cst = conn.prepareCall(sql);
System.out.println(«Результат запроса: «+cst.getString(2));
Для изучения интерфейса CallabeStatement необходимо создать класс использующий main метод для регистрации драйвера и создания соединения с базой данных. Для создания таблицы и заполнения ее данными необходимо использовать отдельные методы (аналогичные приведенным в примере).