Клас Statement

Statementвикористовується для виконання SQL-запитів. Існує три типи класу Statement, які є ніби контейнерами для виконання SQL-виражень через встановлене з'єднання:

  • Statement, базовий;
  • Підпорядкованийдержаву, що успадковує від держави;
  • Переконанийдержавний, успадкований від встановленихдержав.

Всі класи спеціалізуються на виконання різних типів запитів:

  • Statement призначений для виконання простих SQL-запитів без параметрів; містить базові методи для виконання запитів та отримання результатів.
  • PreparedStatement використовується для виконання SQL-запитів з або без вхідних параметрів; додає методи керування вхідними параметрами.
  • CallableStatement використовується для викликів збережених процедур; додає методи для маніпуляції вихідними параметрами.

Після встановлення з'єднання Connection з базою даних воно може використовуватися для виконання SQL-запитів. Об'єктStatementстворюється методом Connection.createStatement.

Для надсилання серверу БД SQL-виразу для виконання необхідно викликати методexecuteQueryоб'єктаStatementі як аргумент передати скрипт запиту :

Методи Statement: executeQuery, executeUpdate, execute

КласStatementмістить три різні методи виконання SQL-виразів: executeQuery, executeUpdate і execute, які викликаються в залежності від тексту SQL-запиту.

executeQuery

МетодexecuteQueryвикористовується в запитах, результатом яких є один набір значень, таких як запитів типу SELECT.

executeUpdate

МетодexecuteUpdateслід використовувати як длявиконання операторів управління даними типу INSERT, UPDATE або DELETE (DML - Data Manipulation Language), і для операторів визначення структури бази даних CREATE TABLE, DROP TABLE (DDL - Data Definition Language).

Результатом виконання операторів INSERT, UPDATE або DELETE є зміни одного або більше рядків таблиці.

Результатом виконання методуexecuteUpdateє ціле значення, що визначає, скільки рядків було модифіковано. Для виразівDML, які не оперують з рядками, значення, що повертається методом executeUpdate, завжди дорівнює нулю.

Метод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

Об'єкт CallableStatement надає уніфікований спосіб виклику збережених процедур у СУБД. Виклик процедури здійснюється з результуючим параметром без нього. Результуючий параметр - це один з типів вихідних (OUT) параметрів, що є значенням збереженої процедури, що зберігається.

Синтаксис виклику збереженої процедури в JDBC показаний нижче. Квадратні дужки означають, що те, що знаходиться між ними, необов'язково, і самі по собі не є частиною синтаксису.

Перші дві форми можуть мати змінну кількість аргументів на вході (параметри IN), виході (параметри OUT) або вхідних та вихідних параметрів одночасно (INOUT-параметри). Знак запитання означає розташування параметра.

МетодsupportsStoredProcedures()класу DatabaseMetaData дозволяє дізнатися, підтримує СУБД збережені процедури чи ні.

Створення об'єкта CallableStatement

Об'єктиCallableStatementстворюються методом prepareCall об'єкта Connection. Приклад, який створюєекземпляр CallableStatement, що містить виклик збереженої процедури setGoodsData з двома аргументами і без параметра, що повертається:

Якими саме параметрами (IN, OUT або INOUT) є знаки питання - залежить від процедури 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) параметри.

Нульове значення у вихідних параметрах, 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реєструє перший параметр як 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-послідовності дати наступний:

де yyyy – це рік, mm – місяць, і dd – день. Наприклад, наступна послідовність буде замінена рядком '28-FEB-15', якщо СУБД сприймає саме такий формат дати.

Аналогічно обробляються escape-конструкції для типів даних TIME і TIMESTAMP:

Мілісекунда (.ms) у TIMESTAMP може бути опущена.

4. escape-послідовність із збереженими процедурами

Для звернення до збереженої процедури з JDBC використовується абоcall, або? = call.

Якщо СУБД підтримує процедури, що зберігаються, то вони можуть викликатися з JDBC за допомогою наступного синтаксису escape-послідовності: