martes, 20 de octubre de 2009

Pasar un Array a un Stored Procedure en Oracle

Durante estos días tuve que hacer la prueba de pasar un array como parámetro a un Stored Procedure en un Oracle 8i desde Java. Al principio pense que era una tarea simple, pero luego encontre que no es tan así dado que me tope con 3 problemas que trataré de describir aquí.

Pero primero dejo dos URL que tienen información de como hacer esto:
* Muy buen foro
* Documentación Oficial de Oracle

Como mencione, al principio pense que usando JDBC podría lograr esto sin tener problemas pero me encontre con algunas limitaciones de JDBC y el tratamiento de los Array, así que tuve que trabajar directamente usando clases propietarias de Oracle. Quedando un código:


DriverManager.registerDriver(new OracleDriver());

String url = "jdbc:oracle:thin:@10.65.72.52:1521:BNPAIS";
Connection conn = DriverManager.getConnection(url, "*******", "*******");

String[] array = {"hola", "mundo"};

ArrayDescriptor descriptor =
ArrayDescriptor.createDescriptor( "T_LISTAVARCHAR2", conn );
ARRAY array_to_pass =
new ARRAY( descriptor, conn, array);

CallableStatement ps = conn.prepareCall("{call TEST.TEST_ARRAY(?,?)}");
ps.setArray(1, array_to_pass);
ps.registerOutParameter(2, OracleTypes.VARCHAR);

ps.execute();

System.out.println( ps.getString(2) );

conn.close();


Ya en la base de datos, primero declaré el tipo de dato ARRAY que use para la prueba (un ARRAY de VARCHAR). Aquí tenia dos opciones, o bien declararlo dentro del package donde iba a tener mi SP o a nivel del schema.
CREATE OR REPLACE TYPE t_listavarchar2 IS TABLE OF varchar2(300)


Opte por la primer opción y enseguida me encontre con el sigueinte error:
java.sql.SQLException: invalid name pattern:


Basicamente, no me encontraba el tipo de dato declarado.:
ArrayDescriptor descriptor = ArrayDescriptor.createDescriptor( "T_LISTAVARCHAR2", conn );


Buscando la solución encontré 2 soluciones posibles, una (la mas simple) es declarar el tipo de datos a nivel del esquema y la otra es crear un sinónimo publico para el tipo (T_LISTAVARCHAR2) con los accesos y permisos correspondientes al usuario que intente acceder.

Una vez solucionado este problema, me encontre por un par de errores de NoClassDefFoundError por falta de algunos JARs. Para solucionarlo además de classes12.jar puse en mi classpath: nls_charset12.jar

Además aquí dejo otro link con información valiosa sobre los jar a colocar en nuestro classpath.

La verdad que no fue complicado, pero tampoco fue tan simple como esperaba.

No hay comentarios:

Publicar un comentario