Que tal amigos,
Una consulta tengo una duda al momento de manejar SPRING JDBC al momento de llamar a PROCEDURE, en un escenario especifico:
Este escenario es cuando quiero obtener el valor del retorno de un ORACLE TYPE. Ya he antes he manejado conectarme enviando contra un PROCEDURE: VARIABLES NORMALES (Input/Output), Cursores (Input/Output), Oracle Types (Solo INPUT), sin problemas pero el escenario de mandar a un PROCEDURE un ORACLE TYPE y que me responda junto con otros 2 VARCHAR un 3er parámetro de salida también de tipo ORACLE TYPE se me está complicando. Aquí el detalle de lo realizado:
-- ******************* TABLA: ******************* --
CREATE TABLE TB_SERV_LLAM(
SLL_ID INTEGER NOT NULL,
SLL_TELEFONO VARCHAR2( 20 ),
SLL_TECNOLOGIA VARCHAR2( 25 ),
SLL_CODIGO VARCHAR2( 10 ),
SLL_MENSAJE VARCHAR2( 100 ),
SLL_PAQUETE VARCHAR2( 25 ),
SLL_PLAN VARCHAR2( 25 ),
SLL_SALDO VARCHAR2( 10 )
)
-- ******************** TYPE: ******************* --
CREATE OR REPLACE TYPE LLAMADAS_TYPE AS OBJECT(
SLL_TELEFONO_IN VARCHAR2( 20 ),
SLL_TECNOLOGIA_IN VARCHAR2( 25 ),
SLL_CODIGO_IN VARCHAR2( 10 ),
SLL_MENSAJE_IN VARCHAR2( 100 ),
SLL_PAQUETE_IN VARCHAR2( 25 ),
SLL_PLAN_IN VARCHAR2( 25 ),
SLL_SALDO_IN VARCHAR2( 10 ),
CONSTRUCTOR FUNCTION LLAMADAS_TYPE RETURN SELF AS RESULT
);
CREATE OR REPLACE TYPE BODY LLAMADAS_TYPE
AS
CONSTRUCTOR FUNCTION LLAMADAS_TYPE RETURN SELF AS RESULT
AS
BEGIN
RETURN;
END;
END;
-- ******************** PROCEDURE (DENTRO DEL PAQUETE): ******************* --
PROCEDURE SP_OBTENER_SERV_LLAM_TYPE( LLAMADAS_TYPE_IN IN RGUERRA.LLAMADAS_TYPE,
ERR_OUT OUT VARCHAR2,
MESSAGE_OUT OUT VARCHAR2,
LLAMADAS_TYPE_OUT OUT RGUERRA.LLAMADAS_TYPE
) AS
LLAMADAS_TYPE_TEMP RGUERRA.LLAMADAS_TYPE;
SLL_CODIGO_AUX VARCHAR2( 20 ) := LLAMADAS_TYPE_IN.SLL_CODIGO_IN;
TEMP_01 VARCHAR2( 20 ) := '';
TEMP_02 VARCHAR2( 20 ) := '';
TEMP_03 VARCHAR2( 20 ) := '';
TEMP_04 VARCHAR2( 20 ) := '';
TEMP_05 VARCHAR2( 20 ) := '';
TEMP_06 VARCHAR2( 20 ) := '';
TEMP_07 VARCHAR2( 20 ) := '';
BEGIN
DBMS_OUTPUT.PUT_LINE( '- SLL_CODIGO_AUX: ' || SLL_CODIGO_AUX );
LLAMADAS_TYPE_TEMP := RGUERRA.LLAMADAS_TYPE(); --INICIALIZACION X CONSTRUCTOR.
IF( SLL_CODIGO_AUX IS NOT NULL ) THEN
SELECT X.SLL_TELEFONO,
X.SLL_TECNOLOGIA,
X.SLL_CODIGO,
X.SLL_MENSAJE,
X.SLL_PAQUETE,
X.SLL_PLAN,
X.SLL_SALDO
INTO TEMP_01,
TEMP_02,
TEMP_03,
TEMP_04,
TEMP_05,
TEMP_06,
TEMP_07
FROM RGUERRA.TB_SERV_LLAM X
WHERE X.SLL_ID = SLL_CODIGO_AUX;
--ASIGNACION DE 'TYPE':
LLAMADAS_TYPE_TEMP.SLL_TELEFONO_IN := TEMP_01;
LLAMADAS_TYPE_TEMP.SLL_TECNOLOGIA_IN := TEMP_02;
LLAMADAS_TYPE_TEMP.SLL_CODIGO_IN := TEMP_03;
LLAMADAS_TYPE_TEMP.SLL_MENSAJE_IN := TEMP_04;
LLAMADAS_TYPE_TEMP.SLL_PAQUETE_IN := TEMP_05;
LLAMADAS_TYPE_TEMP.SLL_PLAN_IN := TEMP_06;
LLAMADAS_TYPE_TEMP.SLL_SALDO_IN := TEMP_07;
LLAMADAS_TYPE_OUT := LLAMADAS_TYPE_TEMP;
--SALIDA:
ERR_OUT := '1';
MESSAGE_OUT := 'PROCESO EXITOSO [OBJETO]';
END IF;
EXCEPTION
WHEN OTHERS THEN
ERR_OUT := TO_CHAR( SQLCODE );
MESSAGE_OUT := SUBSTR( UPPER( SQLERRM ), 1, 100 );
END SP_OBTENER_SERV_LLAM_TYPE;
-- ******************** MÉTODO JAVA: ******************* --
/**
* obtenerServicioLlamadasType
* @param objServicioLlamadasType
* @return DataBaseValidatorBean
*/
@Override
public DataBaseValidatorBean obtenerServicioLlamadasType( final ServicioLlamadasTypeBean objServicioLlamadasType ){
this.logger.info( "*********** [INICIO] - DENTRO: [obtenerServicioLlamadasType - DAO] ***********" );
JdbcTemplate objJdbcTemplate = null;
DataBaseValidatorBean objDataBaseValidatorBean = null;
String OWNER = null;
String PAQUETE = null;
String PROCEDURE = null;
long tiempoInicio = System.currentTimeMillis();
try{
this.logger.info( "DATA SOURCE: [" + this.servicioLlamadasJNDI + "]" );
this.servicioLlamadasJNDI.setLoginTimeout( UtilPropertiesMapper.DB_TIMEOUT_CONEXION );
OWNER = UtilPropertiesMapper.DB_OWNER;
PAQUETE = UtilPropertiesMapper.DB_PAQUETE_OBTENER_TYPE;
PROCEDURE = UtilPropertiesMapper.DB_PROCEDURE_OBTENER_TYPE;
this.logger.info( "PROCEDURE: [" + OWNER + "." + PAQUETE + "." + PROCEDURE + "]" );
this.objJdbcCall = new SimpleJdbcCall( this.servicioLlamadasJNDI );
objJdbcTemplate = this.objJdbcCall.getJdbcTemplate();
objJdbcTemplate.setQueryTimeout( UtilPropertiesMapper.DB_TIMEOUT_EXECUTION );
this.objJdbcCall.withSchemaName( OWNER );
this.objJdbcCall.withCatalogName( PAQUETE );
this.objJdbcCall.withProcedureName( PROCEDURE );
this.objJdbcCall.addDeclaredParameter( new SqlParameter( "LLAMADAS_TYPE_IN", OracleTypes.STRUCT, UtilPropertiesMapper.DB_TYPE_LLAMADAS ) );
this.objJdbcCall.addDeclaredParameter( new SqlOutParameter( "ERR_OUT", OracleTypes.VARCHAR ) );
this.objJdbcCall.addDeclaredParameter( new SqlOutParameter( "MESSAGE_OUT", OracleTypes.VARCHAR ) );
this.objJdbcCall.addDeclaredParameter( new SqlOutParameter( "LLAMADAS_TYPE_OUT", OracleTypes.STRUCT, UtilPropertiesMapper.DB_TYPE_LLAMADAS, new SqlReturnType(){
@Override
public Object getTypeValue( CallableStatement cs,
int colIndx,
int sqlType,
String typeName ) throws SQLException{
STRUCT item = (STRUCT)cs.getObject( colIndx );
Object[] arregloOut = item.getAttributes();
ServicioLlamadasTypeBean objLlamadasRESP = new ServicioLlamadasTypeBean();
objLlamadasRESP.setTelefono( (String)arregloOut[ 0 ] );
objLlamadasRESP.setTecnologia( (String)arregloOut[ 1 ] );
objLlamadasRESP.setCodigo( (String)arregloOut[ 2 ] );
objLlamadasRESP.setMensaje( (String)arregloOut[ 3 ] );
objLlamadasRESP.setPaquete( (String)arregloOut[ 4 ] );
objLlamadasRESP.setPlan( (String)arregloOut[ 5 ] );
objLlamadasRESP.setSaldo( (String)arregloOut[ 6 ] );
return objLlamadasRESP;
}
} ) );
this.objJdbcCall.compile();
SqlTypeValue sqlTypeINPUT = new AbstractSqlTypeValue(){
protected Object createTypeValue( Connection conexion,
int sqlType,
String typeName ) throws SQLException{
StructDescriptor itemDescriptor = new StructDescriptor( typeName, conexion );
ServicioLlamadasTypeBean objLlamadas = objServicioLlamadasType;
STRUCT item = new STRUCT( itemDescriptor, conexion, new Object[]{
objLlamadas.getTelefono(),
objLlamadas.getTecnologia(),
objLlamadas.getCodigo(),
objLlamadas.getMensaje(),
objLlamadas.getPaquete(),
objLlamadas.getPlan(),
objLlamadas.getSaldo()
} );
return item;
}
};
Map objMapIN = new HashMap();
objMapIN.put( "LLAMADAS_TYPE_IN", sqlTypeINPUT ); //IN
objMapIN.put( "ERR_OUT", OracleTypes.VARCHAR ); //OUT
objMapIN.put( "MESSAGE_OUT", OracleTypes.VARCHAR ); //OUT
objMapIN.put( "LLAMADAS_TYPE_OUT", OracleTypes.STRUCT ); //OUT
this.objJdbcCall.execute( objMapIN );
//PARAMETROS [OUT]:
Map objMapOUT = this.objJdbcCall.execute( objMapIN );
String vCodigoErr_OUT = (String)objMapOUT.get( "ERR_OUT" );
String vMensajeErr_OUT = (String)objMapOUT.get( "MESSAGE_OUT" );
ServicioLlamadasTypeBean objServicioLlamadasTypeBean = (ServicioLlamadasTypeBean)objMapOUT.get( "LLAMADAS_TYPE_OUT" );
this.logger.info( "ERR_OUT: " + vCodigoErr_OUT );
this.logger.info( "MESSAGE_OUT: " + vMensajeErr_OUT );
this.logger.info( "LLAMADAS_TYPE_OUT: " + objServicioLlamadasTypeBean );
objDataBaseValidatorBean = new DataBaseValidatorBean();
objDataBaseValidatorBean.setCodigo_OUT( vCodigoErr_OUT );
objDataBaseValidatorBean.setMensaje_OUT( vMensajeErr_OUT );
objDataBaseValidatorBean.setObjLlamadasBeanType( objServicioLlamadasTypeBean );
}
catch( SQLException e ){
this.logger.error( "ERROR: [SQLException] - [" + e.getMessage() + "] ", e );
objDataBaseValidatorBean = new DataBaseValidatorBean();
objDataBaseValidatorBean.setCodigo_OUT( UtilPropertiesMapper.ESTADO_NOK );
objDataBaseValidatorBean.setMensaje_OUT( e.getMessage() );
objDataBaseValidatorBean.setListaDatos( null );
}
catch( Exception e ){
this.logger.error( "ERROR: [Exception] - [" + e.getMessage() + "] ", e );
objDataBaseValidatorBean = new DataBaseValidatorBean();
objDataBaseValidatorBean.setCodigo_OUT( UtilPropertiesMapper.ESTADO_NOK );
objDataBaseValidatorBean.setMensaje_OUT( e.getMessage() );
objDataBaseValidatorBean.setCodServLlam( null );
}
finally{
this.logger.info( "Tiempo TOTAL Proceso: [" + (tiempoInicio-System.currentTimeMillis()) + " milisegundos ]" );
this.logger.info( "*********** [FIN] - DENTRO: [registrarServicioLlamadasType - DAO] ***********" );
}
return objDataBaseValidatorBean;
}
El error que me muestra al ejecutar el PROCESO es el siguiente (indica un tipo de dato invalido, pero ya validé que todos los tipos de campos estan bien):
org.springframework.jdbc.BadSqlGrammarException: CallableStatementCallback; bad SQL grammar [{call RGUERRA.PKG_SERVICIO_LLAMADAS.SP_OBTENER_SERV_LLAM_TYPE(?, ?, ?, ?)}]; nested exception is java.sql.SQLSyntaxErrorException: ORA-00902: tipo de dato no válido
at org.springframework.jdbc.support.SQLExceptionSubclassTranslator.doTranslate(SQLExceptionSubclassTranslator.java:94)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:969)
at org.springframework.jdbc.core.JdbcTemplate.call(JdbcTemplate.java:1003)
at org.springframework.jdbc.core.simple.AbstractJdbcCall.executeCallInternal(AbstractJdbcCall.java:391)
at org.springframework.jdbc.core.simple.AbstractJdbcCall.doExecute(AbstractJdbcCall.java:376)
at org.springframework.jdbc.core.simple.SimpleJdbcCall.execute(SimpleJdbcCall.java:177)
at pe.com.javaman.dummy.servicioLlamadasWS.dao.ServicioLlamadasDaoImp.obtenerServicioLlamadasType(ServicioLlamadasDaoImp.java:366)
Si me apoyan con algún dado se los agradecería ya que en Internet no hay mucha info sobre: SimpleJdbcCall para SqlReturnType.
Saludos.
--
Has recibido este mensaje porque estás suscrito al grupo "Spring User Group Peru" de Grupos de Google.
Para publicar una entrada en este grupo, envía un correo electrónico a spring-user...@googlegroups.com.
Para anular tu suscripción a este grupo, envía un correo electrónico a spring-user-group...@googlegroups.com
Para tener acceso a más opciones, visita el grupo en http://groups.google.com/group/spring-user-group-peru?hl=es.
java.sql.Struct struct =
(weblogic.jdbc.vendor.oracle.OracleStruct)(rs.getObject(2));