tema enviado por Blackcat en Java
tema iniciado el 06/10/2009
Hola, tengo un problema al obtener un tipo de dato desde un Procedimiento PL/SQL (el cual está etiquetado como IN OUT en el procediemiento)
Para hacer la llamada al PL/SQL, estoy usando el framework de Spring.
Por un lado tengo mi procedimiento PL/SQL, que recibe dos parámetros, uno de entrada y el otro de salida. El de salida es un cursor que tengo definido en el paquete pl/sql (ya que lo normal es que me devuelva mas de un registro)
El PL/SQL tiene el siguiete aspecto:
------------------------------------------------------------------------
CREATE OR REPLACE PACKAGE PACKAGE1 AS
TYPE ref_cur IS REF CURSOR;
PROCEDURE myprocedure (name in varchar2, stock_cursor in out ref_cur);
END PACKAGE1;
/
------------------------------------------------------------------------
CREATE OR REPLACE PACKAGE BODY PACKAGE1 AS
PROCEDURE myprocedure (name in varchar2, stock_cursor in out ref_cur)
IS
BEGIN
OPEN stock_cursor FOR 'select
id,
name,
email
from
users
where
name = '''||name||''' ';
END myprocedure;
END PACKAGE1;
/
------------------------------------------------------------------------
en el código Java, intento lo siguiente:
1- Tengo una clase de test (Test_Example), desde la que depuro con el Eclipse.
2- Mi clase Example, es llamada desde la de test y es en la que definen los parámetros de entrada y salida, donde se compila la llamada y donde se ejecuta la llamada al procedimiento (realmente el método execute que se ejecuta es el de la clase extendida StoredProcedure del framework de spring).
3- Tengo una clase GenericProced que extiende de StoredProcedure, donde se obtiene el datasource.
-------------------------------------------------------------------------
GenericProced.java
------------------
import java.util.Map;
import java.util.Properties;
import javax.naming.InitialContext;
import javax.sql.DataSource;
import org.apache.log4j.Logger;
import org.springframework.jdbc.object.StoredProcedure;
public abstract class GenericProced extends StoredProcedure
{
public GenericProced(String InitialContextFactory, String providerUrl, String urlPkgPrefixes , String pool, String procedimiento) throws Exception
{
super(givemeDatasource ( InitialContextFactory, providerUrl, urlPkgPrefixes , pool), procedimiento);
}
/* obtengo el datasource de un fichero de configuracion. esto funciona correctamente */
public static DataSource givemeDatasource (String InitialContextFactory, String providerUrl, String urlPkgPrefixes , String pool) throws Exception
{
Properties prop = new Properties();
prop.setProperty(InitialContext.INITIAL_CONTEXT_FACTORY,InitialContextFactory);
prop.setProperty(InitialContext.PROVIDER_URL, providerUrl);
prop.setProperty(InitialContext.URL_PKG_PREFIXES,urlPkgPrefixes);
//Creamos un contexto y accedemos al recurso.
InitialContext ic = new InitialContext(prop);
DataSource ds = (DataSource)ic.lookup(pool);
return ds;
}// fin método obtenerConexion.
public abstract void definition ();
public abstract Map execute(Object[] objeto);
}
-------------------------------------------------------------------------
-------------------------------------------------------------------------
Example.java
------------
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import oracle.jdbc.OracleTypes;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlOutParameter;
import org.springframework.jdbc.core.SqlParameter;
import es.indra.isia.PL.ProcedimientoGenerico;
public class Example extends GenericProced{
private static final String name_proce = "PACKAGE1.myprocedure ";
private static final String name = "name";
private static final String result = "result";
public Example(String InitialContextFactory, String providerUrl, String urlPkgPrefixes , String pool) throws Exception{
super(InitialContextFactory, providerUrl, urlPkgPrefixes , pool, name_proce);
setFunction(false); //Lo pongo a false, porque es un PROCEDIMIENTO lo que estoy llamando
declareParameter(new SqlParameter(name, OracleTypes.VARCHAR));
declareParameter(new SqlOutParameter("result", OracleTypes.CURSOR, new RowMapper(){
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
MyEntity entity = new MyEntity(
rs.getString("id"),
rs.getString("name"),
rs.getString("email")
);
return entity;
}
}));
compile();
}
public Map execute(Object[] theObject) {
Map datas = new HashMap();
datas.put(name, (String) theObject[0]);
return super.execute(datas);
}
}
-------------------------------------------------------------------------
-------------------------------------------------------------------------
Mi clase RowMapper, MyEntity.java:
----------------------------------
public class MyEntity{
private String id;
private String name;
private String email;
public MyEntity(String id, String name, String email)
{
this.id = id;
this.name = name;
this.email = email;
}
public String toString( ) {
return "Employee :"+id+", "+ name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this. email = email;
}
}
-------------------------------------------------------------------------
-------------------------------------------------------------------------
Test_Example.java
-----------------
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.xml.transform.TransformerException;
import Example;
public class Test_Example{
public static void main(String[] args){
try{
Test_Example test = new Test_Example();
test.inicioDePrueba("Tom");
}catch (Exception e){
e.printStackTrace();
System.out.println("ERRORRR: "+e);
}
}
public void inicioDePrueba(String name) throws TransformerException, Exception{
Example proc = new Example("org.jnp.interfaces.NamingContextFactory",
"jnp://xxx.xxx.xxx.xxx:xxxx",
"org.jboss.naming:org.jnp.interfaces",
"NPS_POOL_NODE");
// RUN
Object[] objects = new Object[1];
objects[0] = name;
Map resp = proc.execute(objects);
Object obj = (Object)resultado.get("result");
}
}
-------------------------------------------------------------------------
Cuando hago debug con el Eclipse, al ejecutar la línea Map resp= proc.execute(objects); se ejecuta sin fallo, pero la variable resp tiene el siguiente aspecto: (se supone que el mñetodo execute debe darme un Map, y lo hace, pero el objeto que me devuelve es de tipo $Proxy3. tengo entendido que es un tipo de dato que usa Sprig para encapsular objetos, pero ¿cómo puedo ibtener mi tipo de dato de forma que pueda procesarlo?)
name...............................value
resp...............................HashMap (id=16)
....[0]............................HashMap$Entry (id=43)
........key........................"result"
........value......................$proxy3 (id=47)
el Objeto $Proxy3, ¿Cómo puedo leerlo?
Muchas gracias.