Java
Introducción
A partir de la versión 8i del sistema RDBMS de Oracle, el lenguaje Java está totalmente integrado en el motor de la base de datos. Por tanto, es posible escribir código Java que se almacenará y ejecutará directamente en la base de datos.
La máquina virtual Java integrada en el motor de Oracle es totalmente compatible con el JDK (Java Development Kit, kit de desarrollo Java) de Sun.
La versión del JDK viene determinada por la versión de Oracle utilizada.
Esta máquina virtual se ejecuta en el mismo proceso y comparte el mismo espacio de memoria que el motor de la base de datos. Esta solución ofrece un excelente tiempo de acceso a los datos.
La máquina virtual es un entorno de ejecución Java que soporta todas las estructuras, métodos y mecanismos de tratamiento de errores propios de Java.
Elegir Java para desarrollar el código del lado del servidor permite obtener una solución escrita completamente en Java y limitar así el número de lenguajes diferentes que es necesario aprender.
El lenguaje Java puede emplearse en la escritura de procedimientos, funciones y disparadores (triggers) de base de datos.
Las ventajas de los procedimientos almacenados son numerosas. Las más importantes son:
-
rendimiento: el código ejecutable lo gestiona el servidor y se mantiene en la memoria del mismo.
-
facilidad de implementación e implantación:...
Cómo cargar procedimientos almacenados
Antes de poder usar los procedimientos, deben cargarse en la base de datos. La carga de procedimientos y su publicación constituyen dos etapas diferentes. Hay muchas clases Java que se cargan y nunca se publican, ya que no presentan interfaz de usuario.
En esta situación, el usuario es un programador de PL/SQL.
Para cargar las clases Java en la base de datos usaremos la utilidad de la línea de comandos loadjava.
1. Generalidades
Para cada clase cargada en la base de datos por loadjava, se crea un objeto y el nombre de dicho objeto hace referencia al nombre completo de la clase Java. En este objeto se almacena el código fuente, el código ejecutable y los diferentes recursos necesarios para la correcta ejecución de la clase. Loadjava también almacena los diferentes valores de las opciones en una tabla.
El programa Java puede crearse mediante una herramienta de desarrollo externa a la base de datos y, a continuación, loadjava permite cargar el archivo .class. Pero también es posible cargar el archivo fuente (.java) y luego compilar el código en la base de datos.
El nombre del objeto creado recibe el nombre completo de la clase Java, es decir, el nombre del paquete seguido del nombre de la clase. Estos nombres pueden tener una longitud máxima de 4000 caracteres en la base de datos. Sin embargo, Oracle solo admite identificadores con una longitud máxima de 30 caracteres para los objetos de la base de datos. Por tanto, es necesario implementar un método de resolución de nombres con el fin de poder manipular estos objetos desde PL/SQL.
2. Permisos de uso
Por omisión, los procedimientos almacenados Java utilizan los privilegios concedidos al usuario de Oracle que ejecuta el procedimiento. Este tipo de resolución de permisos permite personalizar los privilegios concedidos a cada usuario. Además, el código puede centralizarse en un determinado punto de la base de datos y utilizarse de distintas maneras.
Este problema se explica en el siguiente ejemplo:
En este ejemplo, los dos usuarios Pedro y Ana utilizan el mismo procedimiento almacenado Java (Análisis) que se aplica a la tabla Ventas. Dado que el procedimiento almacenado se ejecuta usando los permisos concedidos al usuario que lo ejecuta, accede a las tablas que el usuario posee. Por tanto, en este caso, el mismo código se comparte...
Publicación de procedimientos almacenados
Antes de poder utilizar directamente un procedimiento almacenado Java desde SQL, hay que registrar las referencias a este procedimiento en el diccionario de datos. Esta operación no se realiza de forma automática, ya que el motor de Oracle no puede saber qué métodos serán accesibles desde SQL.
Para un método Java, es necesario crear una función (un método de tipo void) o un procedimiento PL/SQL mediante las instrucciones CREATE FUNCTION y CREATE PROCEDURE. Estas funciones y procedimientos pueden agruparse en un paquete. El cuerpo de estas funciones y procedimientos contendrá la cláusula LANGUAGE JAVA para registrar el nombre completo del método, el valor de retorno y los parámetros.
1. Correspondencia entre tipos de datos
La correspondencia entre los tipos de datos SQL y Java se rige por la siguiente tabla.
Tipo SQL |
Clase Java |
CHAR - NCHAR - LONG - VARCHAR2 - NVARCHAR2 |
oracle.sql.CHAR java.lang.String java.sql.Date java.sql.Time java.sql.Timestamp java.lang.Byte java.lang.Short java.lang.Integer java.lang.Long java.lang.Float java.lang.Double java.lang.BigDecimal byte - short - int - long - float - double |
DATE |
oracle.sql.DATE java.sql.Date java.sql.Time java.sql.Timestamp java.lang.String |
NUMBER |
oracle.sql.NUMBER java.lang.Byte java.lang.Short java.lang.Integer java.lang.Long java.lang.Float java.lang.Double java.lang.BigDecimal byte - short - int - long - float - double |
RAW - LONG RAW |
oracle.sql.RAW byte[ ] |
ROWID |
oracle.sql.CHAR oracle.sql.ROWID java.lang.String |
BFILE |
oracle.sql.BFILE |
BLOB |
oracle.sql.BLOB oracle.jdbc2.Blob |
CLOB - NCLOB |
oracle.sql.CLOB oracle.jdbc2.Clob |
OBJECT |
oracle.sql.STRUCT oracle.jdbc2.Struct |
REF |
oracle.sql.REF oracle.jdbc2.Ref |
TABLE - VARRAY |
oracle.sql.ARRAY oracle.jdbc2.ArrayArray |
2. Creación de una función Java o de un procedimiento Java
Sintaxis
CREATE [OR REPLACE]
{PROCEDURE nombre_procedimiento [(parámetro, ...)]
| FUNCTION nombre_función [(parámetro, ...)] RETURN type_sql}
[AUTHID {DEFINER|CURRENT_USER}]...
Uso de procedimientos almacenados
Una vez cargados y publicados los procedimientos almacenados escritos en Java ya es posible utilizarlos. El objetivo de esta sección es mostrar los diferentes medios que existen para invocar a los procedimientos Java.
1. Llamada a un procedimiento Java desde SQL*Plus
La instrucción CALL
La instrucción CALL permite llamar desde el indicador de PL/SQL a un procedimiento almacenado Java que se haya publicado como función, procedimiento o elemento de un paquete.
Sintaxis
CALL [nombre_esquema.][nombre_paquete.]
{nombre_procedimiento (parámetro,...)|nombre_función(parámetro,...)}
Los parámetros se definen en SQL*Plus y pueden ser valores literales o variables host.
Ejemplo
Uso de la función Cuenta para conocer el número de clientes presentes en la tabla:
SQL> variable numero number
SQL> call cuenta('CLIENTES') into:numero;
Llamada terminada.
SQL> print numero
NUMERO
----------
13
SQL>
Creación de la tabla TTEST y eliminación de la misma a continuación usando el procedimiento Java Borrar:
SQL> create table TTEST (col1 char(5));
Tabla creada.
SQL> call borrar('TABLE','TTEST');
Llamada terminada.
SQL> desc TTEST
ERROR:
ORA-04043: el objeto TTEST no existe
SQL>
Cómo redirigir la salida
Determinados procedimientos almacenados Java emplean el dispositivo estándar de error (System.err) o de salida (System.out) para mostrar determinados datos. Estos dispositivos se pueden redirigir a SQL*Plus utilizando los dos comandos siguientes:
SET SERVEROUTPUT ON [SIZE tamaño]
CALL dbms_java.set_output(tamaño)
Con estos comandos, los datos se muestran una vez que el procedimiento se ha terminado de ejecutar. El parámetro tamaño, cuyo valor predeterminado es 2000 bytes, permite precisar el tamaño del búfer. Este tamaño no puede ser mayor de 1.000.000 bytes.
Ejemplo
Código fuente. El procedimiento...