Використання Java класів та об’єктів у Oracle8i
Що в імені?
Oracle8i з віртуальною машиною Java (VM) зберігає кожен Java-клас як об'єкт схеми. Ім'я об'єкта виводиться з повного кваліфікованого імені класу (але не ідентично йому), і включає імена всіх пакетів, що містять. Наприклад, повним кваліфікованим ім'ям класу OracleSimpleChecker є Oracle.sqlj.checker.
Однак у базі даних Oracle повним кваліфікованим ім'ям Java-об'єкта схеми буде наступне: oracle/sqlj/checker/OracleSimpleChecker
Іншими словами, при збереженні Java-класу в базі даних Oracle точки замінюються слішами.
Ім'я об'єкта в базі даних Oracle, незалежно від того, чи цей об'єкт є таблицею або класом, не може бути довшим за 30 символів. Java не має таких обмежень. Ви можете завантажити Java-клас з ім'ям більше 4000 символів у базу даних Oracle. Якщо ім'я Java містить більше 30 символів, програмне забезпечення Oracle автоматично генерує коректний (менше 31 символу) псевдонім, або "коротке ім'я" для елемента.
Але не турбуйтесь! Вам не доведеться навіть посилатися на псевдоніми, натомість ви можете продовжувати використовувати реальне ім'я елемента у вашому коді. Oracle автоматично встановлює відповідність між цим довгим ім'ям та псевдонімом (ім'ям у схемі), коли це потрібно. Для отримання повного або довгого імені для певного короткого імені можна використовувати функцію DBMS_JAVA.LONGNAME. Наступний запит (збережений у скрипті longname.sql) виводить довгі імена для всіх Java-класів, описаних у поточній (тій, до якої приєднані) схемі бази даних, у яких не збігаються коротке і повне імена:
(Цей запит також міститься у файлі myJava.pkg, у пакеті myJava, використання якого показано нижче.) Припустимо, ви оголосиликлас, з дуже довгим ім'ям, наприклад:
Ви можете переконатися, що Oracle створив власне коротке ім'я таким чином:
Перегляд Java-елементів
Після завантаження вихідних кодів Java, класів та елементів ресурсів у базу даних, можна отримати інформацію про ці елементи з кількох уявлень словника даних (див. таблицю).
Подання словника даних, що містять інформацію про Java-об'єкти
| USER_OBJECTS | Основна інформація про об'єкти для типу JAVA SOURCE |
| ALL_OBJECTS | JAVA CLASS та JAVA RESOURCE |
| DBA_OBJECTS | |
| USER_ERRORS | Будь-які помилки компіляції ваших об'єктів |
| ALL_ERRORS | |
| DBA_ERRORS | |
| USER_SOURCE | Вихідний код ваших джерел Java, лише у разі використання команди CREATE JAVA SOURCE для створення Java-об'єктів схеми |
Ви можете писати запити до цих уявлень або створювати програми, які використовують цю інформацію різними способами.Листинг 1містить скрипт із запитом, що показує всі Java-пов'язані об'єкти у вашій схемі та результат виконання цього запиту. Пропозиція WHERE відсікає об'єкти, які Oracle створив для управління Java-об'єктами. Файл myjava.pkg містить пакетний варіант запиту, представлений уЛистингу 1, який дозволяє переглядати Java-об'єкти, використовуючи наступний процедурний виклик:
Наступна команда виводить список усіх Java-елементів, імена яких починаються на OE:
Стовпець object_name у поданні словника даних user_objects містить повні імена Java-об'єктів схеми, за винятком імен, які довші за 30 символів абомістять символи, що не перекладаються, з набору символів UNICODE. І тут у стовпці object_name зберігається коротке ім'я. Для перетворення коротких імен на повні можна використовувати функцію longname з пакета утиліт DBMS_JAVA (див. наступний розділ).
Пам'ятайте такі характеристики Java-елементів схеми у базі даних:
- При використанні команди loadjava для завантаження Java-елементів у базу даних, вихідний код ваших Java-елементів не переноситься - в базу даних поміщаються тільки такі файли, як class, jar, zip, і java.
- При використанні команди CREATE JAVA вихідний код Java-елементів зберігається в базі даних. Об'єкти типу JAVA SOURCE можна побачити у поданні словника даних USER_OBJECTS, а також у уявленнях ALL_OBJECTS, DBA_OBJECTS для цього елемента. Для отримання вихідного коду, розміщення його в структурах даних PL/SQL та відображення або зміни тексту цього коду можна використовувати процедуру DBMS_JAVA.EXPORT_SOURCE, як про це сказано в наступному розділі.
Експорт Java-ресурсів
Oracle DBMS_JAVA містить процедури для експорту вихідного коду, класів і ресурсів. Взагалі, ці процедури можна використовувати для експорту Java-ресурсів у типи даних Oracle8iBLOB або CLOB.
Приклад процедури вЛистинг 2дає уявлення про те, яким чином можна експортувати вихідний код Java-об'єктів схеми. Можна використовувати команду CREATE JAVA для створення вихідних об'єктів Java, як показано нижче:
Клас не можна експортувати до CLOB, лише до BLOB. Крім того, внутрішнє представлення вихідного коду використовує формат UTF8, тому цей формат також застосовується для зберігання вихідного коду в BLOB.
Надання можливості виведення даних для Java
Коли класиSystem.out і System.err виконуються всередині бази даних, вони посилають свої вихідні дані до поточного файлу трасування. Цей файл не дуже зручне сховище, особливо якщо вам просто потрібно перевірити, чи правильно працює ваш код. Пакет DBMS_JAVA містить процедуру, яку можна викликати, щоб перенаправити вихідні дані до текстового буфера DBMS_OUTPUT, з якого дані автоматично виводяться на екран SQL*Plus. Ось синтаксис виклику цієї процедури:
А ось приклад її використання:
Документація взаємодії між DBMS_JAVA і DBMS_OUTPUT дуже мізерна. За допомогою тестування я виявив такі правила:
- Мінімальний (і заданий за умовчанням) розмір буфера становить лише 2000 байт; максимальний – 1000000 байт. Можна вказувати число, що виходить за ці межі, при цьому не виникатиме помилка (за винятком справді великих чисел); SQL*Plus просто ігноруватиме його.
- Розмір буфера, заданий командою SET SERVEROUTPUT, замінює розмір, вказаний у DBMS_JAVA.SET_OUTPUT. Іншими словами, якщо ви вкажете менше значення під час виклику DBMS_JAVA, воно буде проігноровано SQL*Plus, і буде використовуватися більше значення.
- Якщо вихідні дані Java перевищують розмір буфера, ви не отримаєте повідомлення, яке з'являється при використанні DBMS_OUTPUT, а саме:
Але натомість вихідні дані будуть усічені до розміру буфера, вказаного в SQL*Plus за умовчанням, і виконання коду продовжиться.
Як і у випадку з DBMS_OUTPUT, вихідні дані, що виводяться Java-дзвінками, не будуть відображені до тих пір, поки не закінчиться виконання процедури, через яку вони викликаються.
Обробка виключень у Java
З одного боку, архітектура обробки винятків Java-дуже схожана обробку винятків у PL/SQL. У мові Java, ви збуджуєте (throw) виняток і потім перехоплюєте (catch) його. У мові PL/SQL, ви збуджуєте (raise) виняток та потім обробляєте (handle) його.
З іншого боку, обробка винятків у Java набагато більш трудомістка. Java пропонує базовий клас, який називається Exception. Всі винятки є об'єктами, що базуються на цьому класі, або на класах, що походять від (розширюють) Exception. Ви можете передавати винятки як параметри та маніпулювати ними так само як об'єктами будь-якого іншого класу.
Коли при виконанні SQL-оператора із Java-методу, що зберігається, збуджується виняток, цей виняток є об'єктом підкласу java.sql.SQLException. Цей клас містить два методи, які повертають код повідомлення про помилку Oracle - getErrorCode(), і саме повідомлення про помилку - getMessage() .
Якщо процедура Java, що зберігається, викликана з SQL або PL/SQL, збуджує виняток, який не перехоплюється віртуальною Java-машиною, то програма отримує виняток, збуджений повідомленням про помилку Java. Таким чином, віртуальна Java-машина на сервері бази даних Oracle повідомляє про всі не перехоплені винятки (включаючи винятки, не пов'язані з SQL).
Розглянемо тепер різні способи обробки помилок та результуючі вихідні дані. Припустимо, що ви створили клас, що використовує JDBC, для видалення об'єктів бази даних (дивисьЛистинг 3; цей приклад скопійовано з документації Oracle). Цей рядок перехопить та відобразить на екрані будь-яке SQL-виключення:
Ви можете вбудувати цей клас у процедуру PL/SQL так:
Лістинг 4 показує два результати, один з яких виходить при спробі видалити неіснуючий об'єкт. Результати,представлені у файлі, нагадують про те, що виведення з System.err.println не з'явиться на екрані доти, доки це не буде дозволено явно шляхом виклику DBMS_JAVA.SET_OUTPUT. У будь-якому випадку, однак, виняток не буде поширюватися на блок, що викликає, оскільки воно перехоплюється всередині Java. Після другого виклику процедури dropany можна побачити, що повідомлення про помилку, передане з методу getMessage(), є помилкою Oracle.
є дампом стека помилок, що генерується Java, і спрямований на стандартний висновок, незалежно від того, як обробляються помилки в PL/SQL. Іншими словами, навіть якщо розділ винятків виглядає так:
EXCEPTION WHEN OTHERS THEN NULL;
всі ці повідомлення все одно будуть виведені на екран. Обробка в іншому блоці (якщо він є) буде продовжена. Останні три рядки виводу, що відображається, генеруються викликом DBMS_OUTPUT.PUT_LINE.
Зауважимо, що виникає не помилка Oracle ORA-00942, а загальна Java-помилка ORA-29532. Це справді проблема. Як виявити при перехопленні помилки, що є справжньою помилкою? Схоже, настала черга Людини, що пише Утиліти (Write-a-Utility Man)!
Я звернув увагу, що повідомлення про помилку, що повертається функцією SQLERRM, має такий вигляд:
Отже, можна перевіряти наявність слова java.sql.SQLException, а потім використовувати функцію SUBSTR.Листинг 6містить процедуру, створену для компенсації незручного формату повідомлень про помилки Java. Процедура повертає код помилки та повідомлення для поточної помилки. Блок коду вЛистингу 7демонструє, як можна використовувати цю процедуру (процедура використовує пакет log81, створений файлом log81.pkg, щоб записати інформацію про помилку в журнал).
Хоча ця процедура зберігає інформацію про помилки в журнальних таблицях бази даних, вона, як і раніше, повертає клієнтській сесії стек винятків Java. Наприклад, при запуску скрипту в SQL*Plus, стек виключень Java буде відображатися на екрані.
Легкість інтеграції
Теми, охоплені цією статтею, розглядають деякі прийоми та основні принципи, які використовуються при вбудовуванні функціональних можливостей Java у існуюче Oracle PL/SQL оточення. Хоча магазини, що працюють з базами даних Oracle, ймовірно, не найближчим часом переводитимуть оптову торгівлю на Java, багато хто з нас захоче використовувати Java якнайшвидше. Інформація, наведена в цій статті, має допомогти вам зробити це раціонально та ефективно.
Лістинг 1. Java-пов'язані об'єкти у схемі
Цей запит показує всі Java-пов'язані об'єкти у вашій схемі:
Ось результат виконання цього запиту:
Лістинг 2. Процедура експорту з Oracle DBMS_JAVA
Процедура експорту з Oracle DBMS_JAVA дозволяє витягувати
вихідний код Java-об'єктів схеми.
Листниг 3. Створення класу видалення об'єктів з бази
Ви можете створити клас, який використовує JDBC для видалення об'єктів з бази даних Oracle.
Лістинг 4. Спроба видалення неіснуючого об'єкта
При спробі видалення неіснуючого об'єкта ви отримаєте наступні результати: