Atenção: por essa edição ser muito antiga não há arquivo PDF para download.
Os artigos dessa edição estão disponíveis somente através do formato HTML.

Clique aqui para ler todos os artigos desta edição

Java Stored Procedures no Oracle - Parte II

        A primeira parte deste artigo explorou a utilização do Java no Oracle em três etapas: implementação da classe Java; importação do arquivo fonte ou da classe compilada para o banco de dados e criação das procedures que chamam os métodos da classe.

            O objetivo deste artigo é mostrar a importação dos objetos Java sem o uso dos utilitários loadjava e dropjava, vistos anteriormente. Também veremos como verificar se o suporte a Java está corretamente instalado no servidor Oracle.

Utilizando DDL para criação de Objetos Java  

            Os comandos SQL para esse fim são CREATE, ALTER e DROP JAVA SOURCE/CLASS. Sua sintaxe resumida é a seguinte:

CREATE [OR REPLACE] AND RESOLVE

JAVA {CLASS / SOURCE  NAMED nome_da_classe}

{USING BFILE (directory_object, nome_do_arquivo) / AS código_da_classe}; 

ALTER JAVA {CLASS / SOURCE} “nome_da_classe” RESOLVE;

DROP JAVA {CLASS  / SOURCE} “nome_da_classe”; 

Onde:

§         CLASS/SOURCE – Especifica se o objeto a ser manipulado é uma classe compilada (CLASS) ou um arquivo fonte (SOURCE);

§         Nome_da_classe - É o nome da classe a ser importada;

§         USING BFILE (directory_object, nome_do_arquivo) – O objeto Java pode ser criado a partir de um arquivo de código-fonte ou de um arquivo de classe compilado. Para isso, é necessário indicar neste parâmetro o nome do arquivo e o diretório que o contém.

§         código_da_classe – Se BFILE não for utilizado, podemos inserir o código Java diretamente neste parâmetro.

Considerações Gerais: 

§         Nos comandos ALTER e DROP JAVA o valor do parâmetro “nome_da_classe” tem que ser escrito entre aspas. Nesse caso, a caixa deve ser respeitada;

§         O comando ALTER JAVA é utilizado para forçar a compilação de um objeto do tipo SOURCE ou realizar o resolve de um objeto do tipo CLASS. Um resolve verifica se todas as dependências da classe estão disponíveis. Se a classe for alterada, deve-se executar o comando CREATE OR REPLACE JAVA novamente.

·         A carga de um arquivo para o banco de dados, seja ele fonte ou classe, pode ser efetuada com a função BFILE, que possui dois parâmetros: um objeto do tipo DIRECTORY (um ponteiro para um diretório válido no disco) e o nome do arquivo a ser carregado. O comando para criação do objeto DIRECTORY é:

       CREATE DIRECTORY nome_do_objeto AS ‘diretório’

          Caso o diretório/arquivo indicado em BFILE não exista, um erro será gerado.  

§         Se o arquivo importado for do tipo Source (.java), é necessário utilizar o modificador NAMED, que recebe o nome da classe pública. Se o arquivo já estiver compilado (.class), esse procedimento é desnecessário. Veja um exemplo:

            CREATE AND RESOLVE JAVA SOURCE  NAMED “OlaMundo”

            USING BFILE (DIR, “OlaMundo.java”); 

§         O código-fonte pode ser implementado diretamente no parâmetro SOURCE. Veja um exemplo:

CREATE JAVA SOURCE

NAMED "OlaMundo" AS

public class OlaMundo {

public static String olaMundo() {

  return "Olá Mundo";   }

};

Um Exemplo Prático 

            Como exemplo puramente didático, temos a seguinte situação:

            “É necessário que para cada linha inserida na tabela MOEDA seja gerado um arquivo texto na pasta ‘c:\arquivos’. O nome do arquivo será composto da seguinte forma: “M + seqüência de dez caracteres + .txt”. A seqüência de caracteres será formada pelo valor do campo idmoeda completado com zeros à esquerda.

            Os valores das colunas estarão dispostos em uma única linha, separados por ponto-e-vírgula. Cada arquivo deve corresponder a somente um registro. Este arquivo será posteriormente lido e processado por uma aplicação externa.”

            Para resolver esta solicitação será implementada uma classe Java. Uma stored procedure, associada a um método dessa classe, será disparada por uma TRIGGER de inserção referente à tabela MOEDA.

            Segue o script de criação da tabela MOEDA:

CREATE TABLE MOEDA

   (IDMOEDA NUMBER PRIMARY KEY NOT NULL,

    SIGLA VARCHAR2(10) NOT NULL,

    NOME VARCHAR2(30) NOT NULL,

    TIPO CHAR(1) NOT NULL CHECK (TIPO IN ('P', 'V')),

    PERIODO CHAR(1) NOT NULL CHECK (PERIODO IN ('D', 'M', 'A', 'F')));

            A classe Java se chama Bilhete e implementa o método gerarBilhete. Este método recebe como parâmetro os valores referentes às colunas da tabela MOEDAS. A listagem 1 traz a implementação do método, onde podemos destacar: 

Linhas 7 e 8 -  Temos aqui a assinatura do método a ser publicado na stored procedure. Os métodos importados por Java Stored Procedures devem propagar todas as exceções como SQLException. Essa característica é definida através da declaração throws, na linha 8. Observe que todo o código está protegido por um bloco try..catch e qualquer exceção será regerada como SQLException (o objeto FileWriter pode gerar uma IOException).

Linhas 17 e 18: O valor do campo idmoeda é formatado conforme solicitado: dez posições, alinhado à direita e completado com zeros à esquerda.

Linha 20: “Monta” o nome do arquivo texto;

Linhas 22 a 25: Um objeto do tipo FileWriter cria o arquivo e escreve o conteúdo dos campos de acordo com a formatação solicitada. 

            Como o método vai realizar a gravação de um arquivo em disco, o usuário do banco de dados deve possuir o privilégio javasysprive. O comando abaixo fornece esse direito:

            GRANT javasysprive TO nome_do_usuário 

            Importaremos o arquivo Bilhete.java através do comando CREATE JAVA:

CREATE DIRECTORY PATH_CLASSES AS 'C:\Classes';

CREATE OR REPLACE

AND RESOLVE JAVA SOURCE

NAMED “Bilhete"

USING BFILE (PATH_CLASSES,’Bilhete.java’); 

            Na listagem 2 vemos a implementação da stored procedure que executa o método gerarBilhete. A listagem 3 implementa a Trigger de inserção na tabela MOEDA.

            Note que a simplicidade do exemplo se deve a fins didáticos. A utilização do Java no Oracle pode ser explorada sob uma infinidade de aspectos mais avançados, ficando limitada apenas pela imaginação do administrador.

            Nota: O arquivo texto do exemplo será criado mesmo que a transação seja cancelada. 

01 import java.sql.*;

02 import java.io.*;

03 import java.text.*;

04

05 public class Bilhete

06     {

07        public static void gerarBilhete(int idMoeda, String sigla, String nome, String 08        tipo, String periodo) throws SQLException

09        {     

10        try

11        {

12          String sIdMoeda = “”;

13          sIdMoeda = sIdMoeda.valueOf(idMoeda).trim();

14         

15          int iTamId = sIdMoeda.length();

16       

17           for (int i = 1; i <= (10 – iTamId); i++)

18             { sIdMoeda = “0” + sIdMoeda; }

19       

20            String sNomeArquivo = “c:/arquivos/M” + sIdMoeda + “.txt”;

21     }    

22            FileWriter fw = new FileWriter(sNomeArquivo);

23            fw.write(idMoeda + “;” + sigla + “;” + nome + “;” + tipo + “;” + periodo);

24            fw.flush()

25            fw.close(); 

26           }

27         Catch (Exception e)  

28         { throw new SQLException(e.getMessage());}   

29      }

30     }

Listagem 1

CREATE OR REPLACE PROCEDURE GerarBilhete (IdMoeda Number, Sigla VarChar2, Nome   VarChar2, Tipo Char, Periodo Char) AS LANGUAGE JAVA

    NAME Bilhete.gerarBilhete (int, java.lang.String, java.lang.String,

                java.lang.String, java.lang.String);

Listagem 2  

CREATE OR REPLACE TRIGGER TRGINSERIR_MOEDAS

   AFTER INSERT ON MOEDA

   FOR EACH ROW

    CALL GerarBilhete(:NEW.IDMOEDA, :NEW.SIGLA, :NEW.NOME, :NEW.TIPO, :NEW.PERIODO)

Listagem 3

Verificação do suporte a Java no Oracle 

            A seguir temos alguns comandos SQL para verificar se o suporte a Java está corretamente instalado:

1) SELECT PARAMETER || ‘ = ‘ || VALUE FROM V$OPTION WHERE UPPER(PARAMETER) = 'JAVA';

2) SELECT COUNT(*) FROM DBA_OBJECTS WHERE OBJECT_TYPE LIKE ‘%JAVA%’;

3) DESCRIBE DBMS_JAVA; 

            Se o retorno do comando 1 for ‘Java = True’, o Java está instalado. No entanto, nas versões 8.1.5 à 8.1.7 do Oracle, o contrário nem sempre é verdade.

            O comando 2 verifica a quantidade de objetos Java no banco de dados. O comando 3 verifica a existência do package DBMS_JAVA, que contém as procedures e functions utilizadas pelo Oracle para gerenciamento, compilação e execução de objetos Java.

            Caso o valor retornado pelo comando 2 seja zero, definitivamente o suporte a Java não está instalado neste servidor. Uma instalação parcial ou ‘defeituosa’ pode ser detectada através da comparação do resultado desse comando com a tabela 1, que descreve o número de objetos instalados para cada versão do Oracle.

            Se o comando 3 retornar a mensagem “ORA-04043: o objeto DBMS_JAVA não existe”, a instalação do Java está com problemas ou não foi efetuada.

 

Versão do Oracle

Nº de Objetos Java

8.1.5

4000

8.1.6

8000

8.1.7

10.300

9.2

10.425

                                                                                Tabela 1

A instalação do suporte a Java pode ser efetuada através dos scripts initjvm.sql, initsqlj.sql e initdbj.sql, sempre nessa ordem. Esses scripts são criados automaticamente na instalação do Oracle e ficam localizados normalmente na pasta (Oracle Home)\javavm\install. A execução dos scripts deve ser realizada pelo usuário SYS.