Използване на Java класове и обекти в Oracle8i

Какво има в името?

Oracle8i с Java Virtual Machine (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 класове, описани в текущата (тази, към която е прикачена) схема на база данни, които нямат същите кратки и пълни имена:

(Тази заявка също се съдържа във файла myJava.pkg в пакета myJava, чиято употреба е показана по-долу.) Да предположим, че сте декларираликлас с много дълго име, например:

Можете да проверите дали Oracle е създал собствено кратко име, както следва:

Преглед на Java елементи

След като заредите изходните кодове на Java, класовете и ресурсните елементи в базата данни, можете да получите информация за тези елементи от няколко изгледа на речник на данни (вижте таблицата).

Изгледи на речник на данни, съдържащи информация за Java обекти

Речник на данни Преглежда информацията, съдържаща се в речник
USER_OBJECTSОсновна информация за обекти, за тип JAVA SOURCE
ВСИЧКИ_ОБЕКТИJAVA КЛАС и JAVA РЕСУРС
DBA_ОБЕКТИ
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 за този елемент. Можете да използвате процедурата DBMS_JAVA.EXPORT_SOURCE, за да извлечете изходния код, да го поставите в PL/SQL структури от данни и да покажете или модифицирате текста на този код, както е описано в следващия раздел.

Експортиране на 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 хвърляте изключение и след това го хващате. В PL/SQL създавате изключение и след това го обработвате.

От друга страна, обработката на изключения в Java е много по-трудоемка. Java предлага базов клас, наречен Exception. Всички изключения са обекти, базирани на този клас, или класове, извлечени от (разширяващи) Exception. Можете да предавате изключения като параметри и да ги манипулирате точно като обекти от всеки друг клас.

Когато изключение бъде хвърлено от съхранен метод на Java, докато се изпълнява SQL оператор, това изключение е обект на подкласа java.sql.SQLException. Този клас съдържа два метода, които връщат код на съобщение за грешка на Oracle, getErrorCode() и самото съобщение за грешка, getMessage().

Ако съхранена процедура на Java, извикана от SQL или PL/SQL, хвърли изключение, което не е уловено от виртуалната машина на Java, извикващата програма получава изключението, предизвикано от съобщението за грешка на Java. По този начин JVM на сървъра на базата данни на Oracle отчита всички неуловени изключения (включително не-SQL изключения).

Нека сега разгледаме различните начини, по които се обработват грешките и произтичащия изход. Да приемем, че сте създали клас, който използва JDBC за изтриване на обекти на база данни (вижтеСписък 3; този пример е копиран от документацията на Oracle). Този ред ще улови и покаже всяко SQL изключение на екрана:

Можете да вградите този клас в PL/SQL процедура по следния начин:

Листинг 4 показва два резултата, единият от които се получава при опит за изтриване на несъществуващ обект. резултати,във файла са предоставени напомняния, че изходът от System.err.println няма да се появи на екрана, докато не бъде изрично разрешен чрез извикване на DBMS_JAVA.SET_OUTPUT. И в двата случая обаче изключението няма да бъде разпространено до извикващия блок, тъй като се улавя вътрешно от Java. След второто извикване на процедурата dropany можете да видите, че съобщението за грешка, предадено от метода getMessage(), е грешка на Oracle.

е дъмп на стека за грешки, генериран от Java и записан на стандартен изход, независимо как се обработват грешките в PL/SQL. С други думи, дори секцията за изключване да изглежда така:

ИЗКЛЮЧЕНИЕ КОГАТО 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. Опит за изтриване на несъществуващ обект

Когато се опитате да изтриете несъществуващ обект, ще получите следните резултати: