Що в імені?

Oracle8i з віртуальною машиною Java (VM) зберігає кожен Java-клас як об'єкт
схеми. Назва об'єкту виводиться з повного кваліфікованого імені класу (але не
ідентично йому), і включає імена всіх містять пакетів. Наприклад, повним
кваліфікованим ім'ям класу OracleSimpleChecker є
Oracle.sqlj.checker.OracleSimpleChecker


Однак, в базі даних 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-класів, описаних в поточній (тієї, до якої
приєднані) схемою бази даних, у яких не збігаються коротке і повне
імена:

SELECT object_name shortname,
DBMS_JAVA.LONGNAME (object_name) longname
FROM USER_OBJECTS
WHERE object_type = “JAVA CLASS”
AND object_name != DBMS_JAVA.LONGNAME (object_name);

(Цей запит також міститься у файлі myJava.pkg, в пакеті myJava,
використання якого показано нижче.) Припустимо, ви оголосили клас, з дуже
довгим ім'ям, наприклад:

public class
DropAnyObjectIdentifiedByTypeAndName {

Ви можете упевнитися в тому, що Oracle створив власне коротке ім'я,
наступним чином:

SQL> exec myjava.showlongnames
Short Name | Long Name
___________________________
Short: /247421b0_DropAnyObjectIdentif
Long: DropAnyObjectIdentifiedByTypeAndName

Перегляд 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-об'єкти, використовуючи наступний процедурний виклик:

SQL> exec myjava.showobjects

Наступна команда виводить список всіх Java-елементів, імена яких
починаються на OE:

SQL> exec myjava.showobjects (“OE%”)

Стовпець object_name в поданні словника даних user_objects містить
повні імена Java-об'єктів схеми, за винятком імен, які довше 30
символів або містять неперекладні символи з набору символів UNICODE. У цьому
випадку в стовпці object_name зберігається коротке ім'я. Для перетворення коротких
імен в повні можна використовувати функцію longname з пакету утиліт DBMS_JAVA (см
наступний розділ).


Пам'ятайте наступні характеристики Java-елементів схеми в базі даних:



Експорт Java-ресурсів


Пакет Oracle DBMS_JAVA містить процедури для експорту вихідного коду,
класів і ресурсів. Взагалі кажучи, ці процедури можна використовувати для експорту
Java-ресурсів в типи даних Oracle8i BLOB або CLOB.


Приклад процедури в Лістингу 2 дає уявлення про те, яким чином
можна експортувати вихідний код Java-об'єктів схеми. Можна використовувати
команду CREATE JAVA для створення вихідних Java-об'єктів, як показано нижче:

CREATE OR REPLACE JAVA SOURCE NAMED "Hello"
AS
public class Hello {
public static String hello() {
return "Hello Oracle World";}
};
/
Якщо для функції пакету DBMS_OUTPUT встановлена можливість виведення в
текстовий буфер, то можна переглянути вихідний код, як показано нижче:

SQL> exec show_java_source (“Hello”)
public class Hello {
public static String hello() {
return "Hello Oracle World";}
};

Клас не можна експортувати в CLOB, тільки з BLOB. Крім того, внутрішнє
представлення початкового коду використовує формат UTF8, тому цей формат
застосовується також для зберігання вихідного коду з BLOB.


Надання можливості виведення даних для Java


Коли класи System.out і System.err виконуються всередині бази даних, вони
посилають свої вихідні дані в поточний файл трасування. Цей файл не надто
зручне сховище, особливо якщо вам просто потрібно перевірити чи правильно
працює ваш код. Пакет DBMS_JAVA містить процедуру, яку можна викликати,
щоб перенаправити вихідні дані в текстовий буфер DBMS_OUTPUT, з якого
дані автоматично виводяться на екран SQL * Plus. Ось синтаксис виклику цієї
процедури:

PROCEDURE DBMS_JAVA.set_output (buffersize NUMBER);

А ось приклад її використання:

SET SERVEROUTPUT ON SIZE 1000000
CALL DBMS_JAVA.SET_OUTPUT (1000000);

Документація по взаємодії між DBMS_JAVA і DBMS_OUTPUT дуже мізерна. З
допомогою тестування я виявив такі правила:



ORU-10027: buffer overflow, limit of [] bytes

Але замість цього вихідні дані будуть усічені до розміру буфера, зазначеного в
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-виняток:

catch (SQLException e)
{System.err.println(e.getMessage());}

Ви можете вбудувати цей клас в процедуру PL / SQL наступним чином:

CREATE OR REPLACE PROCEDURE dropany (
tp IN VARCHAR2,
nm IN VARCHAR2
)
AS LANGUAGE JAVA NAME “DropAny.object (
java.lang.String,
java.lang.String)”;
/

Лістинг 4 показує два результати, один з яких виходить при
спробі видалити неіснуючий об'єкт. Результати, представлені у файлі,
нагадують про те, що виведення з System.err.println не з'явиться на екрані до тих
пір, поки це не буде дозволено явним чином, шляхом виклику
DBMS_JAVA.SET_OUTPUT. У будь-якому випадку, однак, виключення не буде
поширюватися на викликає блок, оскільки воно перехоплюється всередині Java.
Після другого виклику процедури dropany, можна побачити, що повідомлення про помилку,
передане з методу getMessage (), є помилкою Oracle.


Якщо закоментувати рядки try і catch в методі DropAny.obj, то результат
виконання буде абсолютно іншим, як показано в Лістингу 5. Тут
потрібно невелике пояснення. Все що написано між

 java.sql.SQLException: ORA-00942: table or view does not exist

і

-29532

являє собою дамп стека помилок, генерований Java, і спрямований на
стандартний висновок, незалежно від того, як обробляються помилки в PL / SQL.
Іншими словами, навіть якщо розділ винятків виглядає наступним чином:


EXCEPTION WHEN OTHERS THEN NULL;


всі ці повідомлення все одно будуть виведені на екран. Обробка в іншому блоці
(Якщо він є) буде потім продовжена. Останні три рядки відображуваного виведення
генеруються викликом DBMS_OUTPUT.PUT_LINE.


Зауважимо, що виникає не помилка Oracle ORA-00942, а загальна Java-помилка
ORA-29532. Це дійсно проблема. Як виявити при перехопленні помилки, що
саме є справжньою помилкою? Схоже, настала черга людина, яка пише
Утиліти (Write-a-Utility Man)!


Я звернув увагу, що повідомлення про помилку, що повертається функцією SQLERRM,
має наступний вигляд:

ORA-29532: Java call …:
java.sql.SQLException: ORA-NNNNN …

Отже, можна перевіряти наявність слова java.sql.SQLException і потім
використовувати функцію SUBSTR. Лістинг 6 містить процедуру, створену з
метою компенсації незручного формату повідомлень про помилки Java. Процедура
повертає код помилки і сповіщення для поточної помилки. Блок коду в Лістингу
7
демонструє, яким чином можна використовувати цю процедуру (процедура
використовує пакет log81, створений файлом log81.pkg, щоб записати інформацію про
помилку в журнал).


Хоча ця процедура зберігає інформацію про помилки в журнальних таблицях бази
даних, вона як і раніше повертає клієнтської сесії стек винятків Java.
Наприклад, при запуску скрипта в SQL * Plus, стек винятків Java буде
відображатися на екрані.


Легкість інтеграції


Теми, охоплені в цій статті, розглядають деякі прийоми та основні
принципи, використовувані при вбудовуванні функціональних можливостей Java в
існуюче Oracle PL / SQL оточення. Хоча магазини, що працюють з базами даних
Oracle, ймовірно, не будуть у найближчому майбутньому переводити оптову торгівлю на
Java, багато хто з нас захочуть використовувати Java як можна швидше. Інформація,
наведена в цій статті, повинна допомогти вам зробити це раціонально і
ефективно.


Лістинг 1. Java-зв'язані об'єкти у схемі

Цей запит показує всі Java-зв'язані об'єкти у вашій схемі:

COLUMN object_name FORMAT A30
SELECT object_name, object_type, status, timestamp
FROM user_objects
WHERE (object_name NOT LIKE “SYS_%”
AND object_name NOT LIKE “CREATE$%”
AND object_name NOT LIKE “JAVA$%”
AND object_name NOT LIKE “LOADLOB%”)
AND object_type LIKE “JAVA %”
ORDER BY object_type, object_name;

Ось результат виконання цього запиту:

SQL> @showjava
OBJECT_NAME OBJECT_TYPE STATUS TIMESTAMP
___________ ____________ _______ ____________
Hello JAVA CLASS VALID 1999-05-19:16:42:27
JFile2 JAVA CLASS VALID 1999-05-26:17:07:11
JFile3 JAVA CLASS VALID 1999-05-27:12:53:46
plsolutions / java / putLn JAVA SOURCE VALID 1999-05-19:16:30:29

Лістинг 2. Процедура експорту з пакета Oracle DBMS_JAVA


Процедура експорту з пакета Oracle DBMS_JAVA дозволяє витягати


вихідний код Java-об'єктів схеми.

/* showjava.sp */
CREATE OR REPLACE PROCEDURE show_java_source (
name IN VARCHAR2,
schema IN VARCHAR2 := NULL
)
IS
b CLOB;
v VARCHAR2(2000) ;
i INTEGER ;
BEGIN
/ * Помістити вихідний код Java в CLOB. * /
DBMS_LOB.CREATETEMPORARY (b, FALSE);
DBMS_JAVA.EXPORT_SOURCE (name, NVL (schema, USER), b);
/ * Читати CLOB в змінну типу VARCHAR2 і відобразити її. * /
i := 1000;
DBMS_LOB.READ (b, i, 1, v);
pl (v) / * запустити pl.sp для створення цієї процедури * /
END;
/

Лістніг 3. Створення класу для видалення об'єктів з бази


Ви можете створити клас, який використовує JDBC, для видалення елементів з бази
даних Oracle.

/* dropany.java */
import java.sql.*;
import java.io.*;
import oracle.jdbc.driver.*;

public class DropAny {
public static void object (String object_type, String object_name)
throws SQLException {
/ / Приєднання до бази даних Oracle за допомогою драйвера JDBC
Connection conn = new OracleDriver().defaultConnection();
/ / Побудова SQL пропозиції
String sql = "DROP" + object_type + "" + object_name;
try {
Statement stmt = conn.createStatement();
stmt.executeUpdate(sql);
stmt.close();
} Catch (SQLException e) {System.err.println (e.getMessage ());}
}
}


Лістинг 4. Спроба видалення неіснуючого об'єкта


При спробі видалення неіснуючого об'єкта, ви отримаєте наступні
результати:

SQL> CONNECT scott/tiger
Connected.
SQL> SET SERVEROUTPUT ON
SQL> BEGIN dropany (“TABLE”, “blip”); END;
/
PL/SQL procedure successfully completed.

SQL> CALL DBMS_JAVA.SET_OUTPUT (1000000);

Call completed.
SQL> BEGIN dropany (“TABLE”, “blip”); END;
/
ORA-00942: table or view does not exist

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*