INTRODUCCIÓN
Cuando se programa con bases de datos Oracle, una de los problemas que debemos resolver es la lectura de un cursor que lo retorna un procedimiento como un parámetro de salida.
En este artículo veremos como resolver este problema utilizando Java - JDBC, especificamente, utilizaremos el objeto CallableStatement.
La base de datos a utilizar es EUREKA, que la puede descargar desde:
http://gcoronelc.blogspot.com/2011/08/base-de-datos-ejemplo.html
PROCEDIMIENTO ALMACENADO
CREACIÓN
Para ilustrar la demostración utilizaremos un procedimiento almacenado para consultar los movimientos de una cuenta:
create or replace procedure usp_egcc_movimientos ( p_cuenta IN cuenta.chr_cuencodigo%TYPE, p_cursor OUT NOCOPY SYS_REFCURSOR ) as begin open p_cursor for select m.chr_cuencodigo cuenta, m.int_movinumero nromov, m.dtt_movifecha fecha, m.chr_tipocodigo tipo, t.vch_tipodescripcion descripcion, t.vch_tipoaccion accion, m.dec_moviimporte importe from tipomovimiento t join movimiento m on t.chr_tipocodigo = m.chr_tipocodigo where m.chr_cuencodigo = p_cuenta; end; /
PRUEBA
Para probar el procedimiento almacenado utilizaremos el siguiente script:
declare v_cursor SYS_REFCURSOR; v_cuenta movimiento.chr_cuencodigo%TYPE; v_nromov movimiento.int_movinumero%TYPE; v_fecha movimiento.dtt_movifecha%TYPE; v_tipo tipomovimiento.chr_tipocodigo%TYPE; v_desc tipomovimiento.vch_tipodescripcion%TYPE; v_accion tipomovimiento.vch_tipoaccion%TYPE; v_importe movimiento.dec_moviimporte%TYPE; begin usp_egcc_movimientos( '00100001', v_cursor ); loop fetch v_cursor into v_cuenta, v_nromov, v_fecha, v_tipo, v_desc, v_accion, v_importe; exit when v_cursor%NOTFOUND; dbms_output.put_line(v_cuenta || ' | ' || v_nromov || ' | ' || v_fecha || ' | ' || v_tipo || ' | ' || v_desc || ' | ' || v_accion || ' | ' || v_importe); end loop; close v_cursor; end; /
No olvidar que debe habilitar la salida:
set serveroutput on
El resultado que se obtiene es similar a los siguiente:
00100001 | 1 | 06/01/08 | 001 | Apertura de Cuenta | INGRESO | 2800 00100001 | 7 | 15/03/08 | 003 | Deposito | INGRESO | 1000 00100001 | 4 | 14/02/08 | 003 | Deposito | INGRESO | 2000 00100001 | 2 | 15/01/08 | 003 | Deposito | INGRESO | 3200 00100001 | 6 | 03/03/08 | 004 | Retiro | SALIDA | 800 00100001 | 5 | 25/02/08 | 004 | Retiro | SALIDA | 500 00100001 | 3 | 20/01/08 | 004 | Retiro | SALIDA | 800
CODIFICACIÓN EN JAVA
FUNDAMENTOS
Se utilizará un objeto de tipo CallableStatement, que permite declarar
un procedimiento almacenado y registrar parámetros de salida
de tipo Cursor.
String sql = "{call usp_egcc_movimientos(?,?)}"; CallableStatement cstm = cn.prepareCall(sql); cstm.setString(1, "00100001"); cstm.registerOutParameter(2, OracleTypes.CURSOR);
Después de ejecutar el procedimiento debemos obtener el cursor en un objeto
de tipo ResultSet.
cstm.executeUpdate(); ResultSet rs = (ResultSet) cstm.getObject(2);
CLASE COMPLETA
A continuación tenemos la clase completa:
package pe.egcc.app; import java.sql.CallableStatement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import oracle.jdbc.OracleTypes; /** * * @author Eric Gustavo Coronel Castillo * @blog gcoronelc.blogspot.com * @fecha 20/05/2014 * @clase DemoCursor * @descripcion: Esta clase sirve para leer un cursor Oracle */ public class DemoCursor { public static void main(String[] args) { Connection cn = null; try { // Parámetros de conexión String driver = "oracle.jdbc.OracleDriver"; String url = "jdbc:oracle:thin:@localhost:1521:XE"; String user = "eureka"; String pwd = "admin"; // Conexión Class.forName(driver).newInstance(); cn = DriverManager.getConnection(url, user, pwd); // Proceso String sql = "{call usp_egcc_movimientos(?,?)}"; CallableStatement cstm = cn.prepareCall(sql); cstm.setString(1, "00100001"); cstm.registerOutParameter(2, OracleTypes.CURSOR); cstm.executeUpdate(); ResultSet rs = (ResultSet) cstm.getObject(2); while(rs.next()){ String texto = rs.getString("cuenta"); texto += " | " + rs.getString("nromov"); texto += " | " + rs.getString("fecha"); texto += " | " + rs.getString("tipo"); texto += " | " + rs.getString("descripcion"); texto += " | " + rs.getString("accion"); texto += " | " + rs.getString("importe"); System.out.println(texto); } rs.close(); cstm.close(); } catch (Exception e) { e.printStackTrace(); } finally{ try { cn.close(); } catch (Exception e) { } } } }
El resultado que se obtiene es el siguiente:
run: 00100001 | 1 | 2008-01-06 00:00:00.0 | 001 | Apertura de Cuenta | INGRESO | 2800 00100001 | 7 | 2008-03-15 00:00:00.0 | 003 | Deposito | INGRESO | 1000 00100001 | 4 | 2008-02-14 00:00:00.0 | 003 | Deposito | INGRESO | 2000 00100001 | 2 | 2008-01-15 00:00:00.0 | 003 | Deposito | INGRESO | 3200 00100001 | 6 | 2008-03-03 00:00:00.0 | 004 | Retiro | SALIDA | 800 00100001 | 5 | 2008-02-25 00:00:00.0 | 004 | Retiro | SALIDA | 500 00100001 | 3 | 2008-01-20 00:00:00.0 | 004 | Retiro | SALIDA | 800 BUILD SUCCESSFUL (total time: 1 second)
Espero que este artículo le sea útil.
CÓDIGO FUENTE: EUREKA-CS-ORACLE-JDBC
En esta sección te presento un video que una aplicación CLIENTE-SERVIDOR desarrollada con Java y Oracle.
Tú tienes acceso al código fuente de esta aplicación, después del video tienes el enlace.