Найкраще з двох світів виклик java з pl

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

У Oracle8i для побудови додатків, які зберігаються і запускаються на сервері бази даних, розробники мають можливість вибрати дві мови програмування: PL / SQL і широко поширений Java. Додатки PL / SQL і Java взаємодіють безпосередньо всередині бази даних, логіка Java-додатків може розширювати існуючі PL / SQL-програми, а збережені Java-програми можуть викликати PL / SQL всередині програмного забезпечення сервера (див. Малюнок 1).

Першим пунктом порядку денного є установка Java Development Kit (JDK) версії 1.1.5 або пізнішої. JDK поставляється з Oracle8i. її також можна завантажити з web-сайту Sun Microsystems Java. Переконайтеся в тому, що змінна оточення CLASSPATH встановлена ​​так, щоб компілятор Java міг визначити місцезнаходження створюваного вами класу, також як і класів, що поставляються Oracle.

Початкові відомості можна з інформації, що публікується в цьому номері замітки 'Ази PL / SQL і Java'.

Доступ до Java з PL / SQL

Доступ до збережених Java-процедурам з бази даних Oracle включає в себе шість основних кроків.

Крок 1: Визначте, які функціональні можливості Java ви хочете використовувати в вашому додатку. Подивіться, чи містять існуючі бібліотеки Java-класів, будь-які зумовлені Java класи, що включають методи з такими функціональними можливостями.

Крок 2: Створіть спеціальний Java-клас, який включає методи, засновані на цих функціональних можливостях.

Крок 3: Відкомпілюйте цей Java-клас, перевірте його і завантажте в базу даних.

Крок 4: Побудуйте PL / SQL програму-пакувальник, яка буде викликати завантажену вами збережену Java-процедуру.

Крок 5: Дайте привілеї, необхідні для PL / SQL програми-пакувальника і збережених Java-процедур, на які вона посилається.

Крок 6: Викличте PL / SQL програму.

Для того, щоб продемонструвати ці дії і представити технологію, яка вам буде потрібно для виконання роботи, я скористаюся дуже простим прикладом. Він полягає в наступному: я хочу мати можливість видаляти файли операційної системи з PL / SQL-програми. До появи Oracle8 версії 8.1 і підтримки Java можливі були тільки такі варіанти:

  • У Oracle7 Release 7.3 можна було посилати повідомлення в канал бази даних, потім програма C-listener перехоплювала повідомлення ( "Delete file X") і виконувала всю роботу.
  • У Oracle8 Release 8.0 можна було створити бібліотеку, яка вказує на динамічно підключається бібліотеку C (DLL) або розділяється бібліотеку. Потім з PL / SQL можна було викликати програму цієї бібліотеки для видалення файлу.

Технологія каналу зручна, але це штучний прийом. Внешнепроцедурний підхід, хоча і є кращим рішенням, але це не такий вже прямий спосіб, особливо, якщо ви не знаєте мови С. З іншого боку, Java містить зумовлені класи, які пропонують потужні, прості у використанні інтерфейси програмування додатків (APIs) для широкого спектра функціональних можливостей, включаючи файловий ввід / вивід.

Крок 1. Пошук необхідних зумовлених функціональних можливостей Java.

public class java.io.File public boolean delete ();
public boolean mkdir ();
>

Іншими словами, я можу викликати булевий Java-метод для видалення необхідного файлу. Якщо метод видаляє файл, то він повертає TRUE, інакше він повертає FALSE.

Збережені процедури Java

КРОК 2. Побудова користувальницького Java-класу

Ви можете здивуватися, чому необхідно будувати інший Java-клас на базі класу File. Чому не можна просто викликати File.delete безпосередньо з програми-пакувальника? На це є дві причини:

  • Java-метод, майже у всіх випадках (крім статичних методів і методів класу), виконується із спеціального об'єкта, який створюється за рахунок класу. Ви не можете створити (instantiate) Java-об'єкт з PL / SQL і потім викликати метод для цього об'єкта.
  • Типи даних в Java і PL / SQL не збігаються один з одним безпосередньо. Наприклад, ви не можете передати булевий тип даних Java безпосередньо в булевий тип даних PL / SQL.

Отже, вам необхідно побудувати новий клас, який буде:

  • Створювати об'єкт з класу File
  • Викликати метод delete для цього об'єкту
  • Повертати значення, яке зможе інтерпретувати PL / SQL

Нижче наводиться простий клас, який я створив, щоб використовувати переваги методу File.delete:

import java.io.File;
public class JDelete public static int delete (String fileName) File myFile = new File (fileName);
boolean retval = myFile.delete ();
if (retval) return 1; else return 0;
> // method delete
> // class Jdelete

Метод JDelete.delete просто створює порожній об'єкт File для заданого імені файлу, так що я можу викликати метод delete для цього файлу. Оголошуючи метод статичним, я роблю його доступним, уникаючи необхідності створювати об'єкт: статичні методи зв'язуються з класами, а не з об'єктами цих класів.

Цей клас підкреслює деякі важливі відмінності між Java і PL / SQL:

  • Java не має операторів BEGIN і END для блоків, циклів і операторів умови. Замість цього, потрібно використовувати відкривається дужку (), щоб закрити його.
  • Java чутлива до регістру, що означає, що if зовсім не те ж саме, що IF або If або iF.
  • Оператор присвоювання Java - це просто знак 'дорівнює' (=), на відміну від складного символу (: =) в PL / SQL.
  • При виклику методу, що не має аргументу (такого як метод delete в цьому прикладі), необхідно, проте, вказувати що відкриваються і закриваються дужки; в іншому випадку компілятор Java буде намагатися інтерпретувати метод як член класу або структуру даних.

КРОК 3. Компіляція, тестування і завантаження класу в базу даних Oracle

Для компіляції написаного мною класу, мені потрібно перейти в директорію, в якій розташований цей клас, і виконати з командного рядка команду javac, використовуючи ім'я класу в якості аргументу:

D: \ Java> javac JDelete.java

Тепер має сенс перевірити метод перед завантаженням його в базу даних. Завжди краще створити і відразу перевірити. Java надає простий спосіб, щоб зробити це: метод main. Якщо ви передбачте в вашому класі метод void, що викликає main, і дасте йому коректний список аргументів, ви зможете потім викликати клас, і його код виконається. Додайте метод main до JDelete, як показано нижче:

public class JDelete public static int delete
public static void main (String args []) System.out.println (delete (args [0]));
> // method main
> // class JDelete

Іншими словами, метод викликає delete для першого значення, переданого класу, і потім відображає значення, що повертається. Тепер потрібно перекомпілювати клас і запустити його (цей приклад запущений з вікна DOS):

D: \ Java> javac JDelete.java
D: \ Java> java JDelete c: \ temp \ te_employ.pks
1
D: \ Java> java JDelete c: \ temp \ te_employ.pks
0

Зверніть увагу, що під час першого виклику JDelete, була відображена 1 (TRUE), тому що мій метод видалив файл. При повторному запуску цієї команди, була відображений 0, тому що метод не зміг видалити файл, який вже не існує.

Тепер, коли я переконався, що метод delete працює, я використовую команду loadjava для його завантаження. loadjava є утилітою Oracle, яку запускає з командного рядка операційної системи, яка завантажує елементи коду Java (класи. jar файли і тому подібні) в базу даних Oracle. Я завантажив клас в схему SCOTT бази даних Oracle:

D: \ Java> loadjava -user scott / tiger -oci8 -resolve JDelete.class

Для того, щоб перевірити, що клас дійсно завантажився, я звертаюсь вміст подання словника даних USER_OBJECTS (див. Лістинг 1).

На цьому закінчуються проблеми, пов'язані з характерними для Java кроками. Настав час повернутися в знайомий світ PL / SQL.

КРОК 4. Побудова PL / SQL специфікації виклику

Я хочу надати всім можливість приєднуватися до мого екземпляру бази даних, щоб видаляти файли з PL / SQL. Для досягнення цього, я створюю специфікацію виклику (відому як call spec), зовні схожу на функцію PL / SQL, але насправді це всього лише оболонка для виклику основного Java-коду:

CREATE OR REPLACE FUNCTION fDelete
(File IN VARCHAR2)
RETURN NUMBER
AS LANGUAGE JAVA
NAME 'JDelete.delete (java.lang.String)
return int ';
/

Реалізація функції fDelete складається з рядків, що описують виклик Java-методу. Список параметрів повинен відповідати параметрам методу, але замість кожного параметра потрібно вказувати повне точну назву типу даних. (Java не використовує глобальні змінні; кожне поле і метод прив'язані до класу, а кожен клас є частиною пакета. Така ієрархія забезпечує механізм повного складного імені та запобігає виникненню суперечностей в просторі імен.) В даному випадку це означає, що я не можу просто набрати String, але замість цього повинен додати повне ім'я пакета, що містить клас String. У реченні RETURN просто вказано int для цілих. int це один з елементарних типів даних Java, а не клас, отже, це його повна специфікація.

КРОК 5. Створення привілеїв бази даних Oracle

Oracle8i пропонує дві нові ролі для підтримки безпеки Java. Багато операцій, орієнтовані на Java, не потребують цих ролях, але якщо потрібно взаємодіяти з операційною системою, наприклад, звертатися до файлів операційної системи або змінювати їх, необхідно мати роль Javasyspriv або Javauservpriv. Надання цієї ролі нічим не відрізняється від надання будь-якої іншої ролі бази даних. Наприклад, для того, щоб SCOTT міг виконувати будь-яку пов'язану з Java операцію, потрібно виконати наступну команду з-під облікового запису SYSDBA:

GRANT JAVASYSPRIV TO SCOTT;

Якщо ви хочете накласти деякі обмеження на те, що користувач може робити за допомогою Java, то замість цього потрібно виконати таку команду:

GRANT JAVAUSERPRIV TO SCOTT;

Для створення або видалення файлу з використанням Java, необхідно мати роль JAVASYSPRIV; для читання або запису файлу досить мати роль JAVAUSERPRIV.

При ініціалізації JServer віртуальної Java-машини, встановлюється примірник Java-класу Java Security Manager (Менеджер Безпеки Java) java.lang .SecurityManager. Кожен користувач бази даних має дінаміческійідентіфікатор (ID). який відповідає власнику сесії, коли користувач звертається до Java методам з PL / SQL. Якщо користувач, який не має достатніх привілеїв, спробує виконати операцію, то віртуальна Java-машина порушить виняток java.lang.SecurityException (аналогічно концепції порушення винятків в PL / SQL). У SQL * Plus ви побачите наступне:

ORA-29532: Java call terminated by uncaught Java exception: java.lang.SecurityException

При запуску Java-методів всередині бази даних, можуть виникати різні проблеми, пов'язані з безпекою, особливо, коли програма взаємодіє з файлової системою на стороні сервера або іншими ресурсами операційної системи. Сервер бази даних Oracle слід одному з двох правил для перевірки безпеки перед виконанням операцій введення / виводу:

  • Якщо динамічному ідентифікатором надано привілей JAVASYSPRIV, то Security Manager дозволяє виконання операції;
  • Якщо динамічному ідентифікатором надано привілей JAVAUSERPRIV, то Security Manager слід тим же правилам, які використовуються PL / SQL-пакетом UTL_FILE для визначення, чи є операція дозволеної, які свідчать, що файл повинен знаходитися в директорії, зазначеної в параметрі UTL_FILE_DIR в файлі ініціалізації бази даних .

КРОК 6. Виклик програми PL / SQL

Тепер компоненти Java знаходяться на своїх місцях, необхідні привілеї надані, я компілює PL / SQL функцію і потім виконую чарівний, раніше важкий трюк:

SQL> @ fdelete.sf
Function created.
Input truncated to 12 characters

SQL> exec DBMS_OUTPUT.PUT_LINE (
fdelete ( 'c: \ temp \ te_employee.pkb'))
1

SQL> exec DBMS_OUTPUT.PUT_LINE (
fdelete ( 'c: \ temp \ te_employee.pkb'))
0

Ви можете також побудувати утиліти на базі цієї функції. Наприклад, ви можете створити процедуру, яка видаляє всі файли в рядках вкладеної таблиці. Або ще краще, ви можете написати процедуру, яка приймає на вхід ім'я директорії і фільтр (наприклад, "все файли схожі на * .tmp ') і видаляє всі файли з директорії, які проходять фільтр.

Погляд у майбутнє

Якщо ви ніколи раніше не використовували Java, я сподіваюся, що тепер ви скажете собі: 'Гей, це легше, ніж я припускав!' У Java є набагато більше можливостей, ніж я торкнувся в цій статті, але приклад JDelete повинен дати вам почуття впевненості в тому, що використання Java можливо. Вбудовування Java в додатки PL / SQL може, звичайно, бути набагато більш складним, в залежності від того, що саме ви збираєтеся робити. Я розгляну деякі з цих проблем в наступній статті цієї серії.

Основний Глосарій Java

Клас (class) Будівельний блок Java-додатків, клас є групою елементів даних (членів), з якими пов'язані програми (методи), які виконують операції над цими даними. Пакет PL / SQL в чомусь схожий на клас, за винятком того, що ви не можете створювати окремий об'єкт із пакета, тому він більше схожий на статичний Java-клас.

Типи даних (datatypes) Все в Java визначається через клас, крім елементарних типів даних. Так, String є класом, тому коли ви оголошуєте змінну типу String, ви створюєте об'єкт, заснований на цьому класі. Елементарні типи даних Java включають чотири типи цілих, а також boolean, char, double, і float.

Реалізація (instantiation) Для створення приватного примірника з більш загальної структури, потрібно оголосити об'єкт як екземпляр або реалізацію класу. У мові PL / SQL ви можете оголосити тип запис (TYPE) і потім оголосити екземпляр запису, заснований на цьому типі.

Член (member) Клас може містити будь-яку кількість змінних, методів та інших класів (класів таких як в Java 1.1), які всі разом називаються членами класу. Клас може бути визначений усередині своїх членів, які містять інформацію про клас в цілому (статичні члени) або про реалізації об'єктів цього класу. Члени класу схожі на змінні рівня пакета в PL / SQL. Однак, кожен раз коли ви створюєте об'єкт з класу, ви отримуєте новий набір членів. Пакет має тільки одну реалізацію своїх даних під час сесії бази даних Oracle.

Метод (method) метод - це іменована група операторів мови програмування Java, які пов'язані з певним класом і які можуть бути викликані для об'єктів, які є реалізаціями класу. В Java ви можете визначити статичні методи (також звані методами класу), які можуть бути доступні безпосередньо з класу без створення об'єкта. Метод main також завжди оголошується як статичний.

Об'єкт (object) Відомий також як екземпляр, об'єкт - це елемент виконуваного коду, який особливим чином реалізує основну структуру класу. Клас є загальним шаблоном типів (sorts), які надають структуру і правила для цієї структури. У загальному сенсі об'єкт - це елемент даних, яким ви маніпулюєте в вашому додатку.

Пакет (package) Пакет - це елемент мови Java, який використовується для угруповання споріднених класів під загальним ім'ям. Всі пакети в Java API згруповані в один пакет, званий java. Усередині пакета java знаходяться інші пакети, згруповані за функціональними можливостями, наприклад, пакет java.util містить основні класи утиліт.

Програмування на Java присвячені сотні книг. Ось деякі з моїх фаворитів:

Для перевірки, чи існує клас і його методи в базі даних

запитаємо вміст подання словника даних USER_OBJECTS,

використовуючи наступний запит:

# 9; SELECT object_name, object_type, status, timestamp

# 9; WHERE (object_name NOT LIKE 'SYS_%'

# 9; # 9; # 9; AND object_name NOT LIKE 'CREATE $%'

# 9; # 9; # 9; AND object_name NOT LIKE 'JAVA $%'

# 9; # 9; # 9; AND object_name NOT LIKE 'LOADLOB%')

# 9; AND object_type LIKE 'JAVA%'

# 9; ORDER BY object_type, object_name;

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

# 9; Object Name # 9; Object Type # 9; Status # 9; # 9; Timestamp

Схожі статті