Программирование >>  Oracle 

1 ... 317 318 319 [ 320 ] 321 322 323 ... 469


1376

Глава 19

Полезные примеры

Я свято верю, что, если задачу можно решить с помощью одного SQL-оператора, это надо делать. Никогда не используйте, например, цикл FOR по курсору, если достаточно выполнить оператор UPDATE. Если задачу нельзя решить в SQL, попытайтесь решить ее в PL/SQL. Никогда не пишите внешнюю процедуру на языке Java или С, разве что задачу нельзя решить в PL/SQL или реализация на языке С существенно повышает производительность. Если по техническим причинам задачу нельзя решить с помощью PL/SQL, попробуйте решить ее на языке Java. Однако использование Java требует дополнительных ресурсов - памяти, процессорного времени и времени на первоначальный запуск виртуальной машины JVM. Использование PL/SQL также требует дополнительных ресурсов, но они уже выделены, ничего дополнительно запускать не надо.

Теме не менее ряд задач нельзя решить с помощью языка PL/SQL, а при использовании Java они решаются элементарно. Ниже представлены полезные фрагменты Java-кода, используемые мной в повседневной практике. Это, конечно, не исчерпывающий список, а лишь вершина айсберга. В приложении А примеры использования языка Java в Oracle рассмотрены более широко.

Генерация списка файлов каталога

Пакет UTL FILE, который мы уже несколько раз использовали по ходу изложения, хорошо справляется с чтением и записью текстовых файлов. Очень часто, однако, необходимо обработать все файлы в указанном каталоге. Этого пакет не позволяет сделать. Для получения списков файлов каталога нет встроенных методов ни в SQL, ни в PL/SQL. На Java его очень легко получить. Вот как это делается:

tkyte@TKYTE816> create global temporary table DIR LIST

2 (filename varchar2(2 55) )

3 on commit delete rows

4 / Table created.

В этой реализации я решил использовать для возвращения результатов из хранимой процедуры на Java временную таблицу. Я считаю этот метод наиболее удобным, потому что он позволяет в дальнейшем легко сортировать список и выбирать файлы с нужными именами.

Необходим следующий фрагмент Java-кода:

tkyte@TKYTE816> create or replace

2 and compile java source named DirList

3 as

4 import java.io.*;

5 import java.sql.*;

7 public class DirList

9 public static void getList(String directory)

10 throws SQLException

11 {



Хранимые процедуры на языке Java

1377

12 File path = new File(directory);

13 String[] list = path.list();

14 String element; 15

16 for(int i = 0; i < list.length;

17 {

18 element = list[i];

19 #sql { INSERT INTO DIR LIST (FILENAME)

20 VALUES (:element) };

21 )

22 }

24 )

25 /

Java created.

Я решил использовать SQLJ, чтобы сократить программу. Подключение к базе данных уже выполнено, поэтому реализация с помощью интерфейса JDBC потребовала лишь нескольких дополнительных строк кода. Но с помощью препроцессора SQLJ выполнять SQL-операторы в Java так же просто, как и в PL/SQL. Теперь, конечно же, необходимо создать спецификацию вызова:

tkyte@TKYTE816>create or replace

2 procedure get dir list(p directory in varchar2)

3 as language java

4 name DirList.getList(java.lang.String);

Procedure created.

Прежде чем запускать эту процедуру, следует учесть еще один нюанс. Необходимо предоставить процедуре право делать то, что она должна - читать список файлов каталога. В данном случае я обладаю правами администратора базы данных, поэтому могу предоставить соответствующие привилегии сам себе, но обычно приходится обращаться с соответствующим запросом к администратору. Если помните, во введении к этой главе я писал:

... Java-код всегда работает с правами владельца ПО Oracle, поэтому хранимая процедура на Java при предоставлении соответствующих привилегий может переписать файл параметров инициализации сервера, INIT.ORA (или другие, еще более важные файлы, например файлы данных).

Сервер Oracle защищается от этого следующим образом: для выполнения небезопасных действий необходимо явно получить соответствующую привилегию. Попытавшись использовать эту процедуру до получения необходимых привилегий, мы получим следующее сообщение об ошибке:

tkyte@TKYTE816> execget dir list(с:\temp) ; BEGIN get dir list<c:\temp); END;

ERROR at line 1:



1378

Глава 19

ORA-2 9532: Java call terminated by uncaught Java exception: java.security.AccessControlException:

the Permission (java.io.FilePermission c:\temp read) has not been granted by dbms java.grant permission to

SchemaProtectionDomain(TKYTEPolicyTableProxy(TKYTE)) ORA-06512: at TKYTE.GET DIR LIST , line 0

ORA-06512: at line 1

Поэтому предоставим себе право получать список файлов в соответствующем каталоге:

tkyte@TK:E816> begin

2 dbms java.grant permission

3 (USER,

4 java.io.FilePermission,

5 c:\temp,

6 read);

7 end;

PL/SQL procedure successfully completed. И можно выполнять процедуру:

tkyte@TKYTE816> exec get dir list(c:\temp); PL/SQL procedure successfully completed. tkyte@TKYTE816> select * from dir list where rownum < 5; FILENAME

a.sql

abc.dat

activation

activation8i.zip

Соответствующие права доступа определяются спецификацией Java2 Standard Edition (J2SE) и подробно описан! на странице http: java.sun.eom/j2se/l.3/docs/api/java/ security/Permission.html. В приложении А мы подробно рассмотрим пакет DBMSJAVA и его использование.

Есть еще один нюанс, который необходимо учитывать. Oracle 8.1.6 - первая версия СУБД Oracle, поддерживающая систему прав доступа, задаваемую спецификацией J2SE. В Oracle 8.1.5 для этого приходилось использовать роли. К сожалению, роль б]ла ровно одна: JAVASYSPRIV. Ее использование будет подобно предоставлению роли администратора базы данных каждому пользователю только потому, что ему необходимо создать представление, - это слишком мощная роль для выполнения такого простого действия. При наличии роли JAVASYSPRIV можно делать все, что угодно. Будьте осторожны при использовании этой роли в версии 8.1.5 и постарайтесь перейти на следующие версии, где принята более избирательная модель привилегий.

Выполнение команды ОС

Если бы я получал десятицентовую монету всякий раз, отвечая на вопрос о том, как выполнить команду ОС! До появления поддержки языка Java в СУБД, это действитель-



1 ... 317 318 319 [ 320 ] 321 322 323 ... 469

© 2006 - 2025 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика