Mapeamento de parametros entre PL e Java

9 respostas
F

Boa tarde pessoal!

Depois de bastante tempo estou voltando a reutilizar o fórum. Fazem mais de um dia (desde sexta-feira) que estou tentando mapear o retorno de uma PL para meu código Java e não estou conseguindo. O retorno da PL é o seguinte:

pi_num_agencia(String), pi_num_posto(String), pi_cod_usuario(String), pi_num_conta(String), pi_cod_produto(String), pi_vlr_financiado(Float), pi_qtd_parcelas(Float), pi_data_atual(Date), pi_aplicacao(String), pi_operacao(String), po_contrata_online(Integer), po_data_efetivacao(Date), po_data_hora_inclusao(Date), po_des_autenticacao(String), pi_num_agencia_term(String), pi_num_posto_term(String), pi_data_pri_vcto(Date), pi_comitar(String)

No lado Java, o mapeamento é realizado da seguinte forma:

ParameterHandler<ResultSet> handler = new ParameterHandler<ResultSet>() { public void setParameters(StatementWrapper s) throws SQLException { TypeManager.registerCursor(1, s); s.setString(2, piNumAgencia); s.setString(3, piNumPosto); s.setString(4, piCodUsuario); s.setString(5, piNumConta); s.setString(6, piCodProduto); s.setBigDecimal(7, piVlrFinanciado); s.setBigDecimal(8, piQtdParcelas); s.setDate(9, piDataAtual); s.setString(10, piAplicacao); s.setString(11, piOperacao); s.registerOutParameter(12, java.sql.Types.INTEGER); s.registerOutParameter(13, java.sql.Types.DATE); s.registerOutParameter(14, java.sql.Types.DATE); s.registerOutParameter(15, java.sql.Types.VARCHAR); s.setString(16, piNumAgenciaTerm); s.setString(17, piNumPostoTerm); s.setDate(18, piDataPrimVencimento); s.setString(19, piComitar); }
Tenho como resultado a seguinte exceção:

java.sql.SQLException: ORA-06550: line 1, column 14: PLS-00306: wrong number or types of arguments in call to 'FNC_SIMULACAOCONTRATACAO' ORA-06550: line 1, column 7: PL/SQL: Statement ignored

Parece meio óbvio que o problema está no mapeamento dos parametros. Não sou eu quem desenvolvo a PL, somente recebo a MI com a definição dos parametros de entrada e saída. Mas estou incapaz de corrigir este problema. Quem sabe alguém de vocês enxerga alguma coisa óbvia neste mapeamento que não estou vendo.

Agradeço muito!
Att.

9 Respostas

F

Pelo erro, vi que o nome do objeto PL/SQL é uma função, estou correto?

Se sim, uma função em PL/SQL só retorna um valor, definido na cláusula RETURN no código da função PL/SQL. Se você precisa retornar vários valores, você deve criar uma Procedure cujos parâmetros sejam OUT. Você pode até usar nos parâmetros da função, clausulas OUT, mas isso não é recomendado pela Oracle e não segue as boas práticas de programação em PL/SQL. Abaixo segue um exemplo de criação de uma procedure que “retorna” dois valores:

CREATE OR REPLACE PROCEDURE MYPROCEDURE (PARAM1 OUT NUMBER, PARAM2 OUT VARCHAR2) IS ...

Em PL/SQL, você pode usar essa procedure da seguinte forma

DECLARE VAR1 NUMBER; VAR2 VARCHAR2(10); BEGIN MYPROCEDURE (VAR1, VAR2); DBMS_OUTPUT.PUT_LINE('Variavel 1: ' || VAR1 || ' --- Variável 2: ' || VAR2); END;

F

Exato, é uma função. Essa função tem como você pode ver, quatro parametros de saída (parametros out do número 12 até o número 15) e na primeira posição do retorno, ela retorna o cursor.

A PL eu não posso alterar, somente consumi-la e eu preciso trabalhar com o que ela me retorna. Então por mais que entenda e concorde que ela não siga o padrão da oracle eu preciso me virar aqui para conseguir mapear o retorno dela. Executando a PL via test script no PL/SQL developer, ela funciona certinho.

Obrigado pela dica.
Att.

F

Pelo que entendi, ela tem 4 parâmetros OUT e mais o retorno da função, correto?

Nunca trabalhei com retornos de funções em PL/SQL + Java, mas pelo que vi em seu código, ele está recebendo 4 parâmetros de retorno, sendo que a função retorna 5 (4 parâmetros OUT e o return padrão dela). Então você poderia fazer um teste e alterar o código Java para ele receber 5 valores da função PL/SQL.

F

Você está certo, são 04 parametros out e mais o retorno da própria função. Mas o retorno da própria função é obtido assim

TypeManager.registerCursor(1, s); conforme você pode ver na linha 03 do código no meu primeiro post e assim para os 04 parametros out

s.registerOutParameter(12, java.sql.Types.INTEGER); s.registerOutParameter(13, java.sql.Types.DATE); s.registerOutParameter(14, java.sql.Types.DATE); s.registerOutParameter(15, java.sql.Types.VARCHAR);

Já trabalho com os retornos de função dessa mesma maneira que exemplifiquei acima em outras funções. Mas posso tentar fazer um arranjo para testar uma situação conforme você descreveu, acho válido, somente não possível agora.

Obrigado novamente!

M

nao sei se estou falando bobeira, mas eu uso procedures criando um callablestatement. coloca o seu pra gente ver se vc estiver usando eh claro!

[]'s

F
Segue:
@FunctionCall(value = "FNC_SimulacaoContratacao", paramCount=18)
	private ResultSet fncSimulacaoContratacao(
			final String piNumAgencia,
			final String piNumPosto, 
			final String piCodUsuario,
			final String piNumConta, 
			final String piCodProduto,
			final BigDecimal piVlrFinanciado, 
			final BigDecimal piQtdParcelas,
			final Date piDataAtual, 
			final String piAplicacao,
			final String piOperacao, 
			final String piNumAgenciaTerm,
			final String piNumPostoTerm, 
			final Date piDataPrimVencimento,
			final String piComitar,
			final Object[] statusRetorno) throws SQLException {
		

		ParameterHandler<ResultSet> handler = new ParameterHandler<ResultSet>() {
			public void setParameters(StatementWrapper s) throws SQLException {
				TypeManager.registerCursor(1, s);
				s.setString(2, piNumAgencia);
				s.setString(3, piNumPosto);
				s.setString(4, piCodUsuario);
				s.setString(5, piNumConta);
				s.setString(6, piCodProduto);
				s.setBigDecimal(7, piVlrFinanciado);
				s.setBigDecimal(8, piQtdParcelas);
				s.setDate(9, piDataAtual);
				s.setString(10, piAplicacao);
				s.setString(11, piOperacao);
				s.registerOutParameter(12, java.sql.Types.INTEGER);
				s.registerOutParameter(13, java.sql.Types.DATE);
				s.registerOutParameter(14, java.sql.Types.DATE);
				s.registerOutParameter(15, java.sql.Types.VARCHAR);
				s.setString(16, piNumAgenciaTerm);
				s.setString(17, piNumPostoTerm);
				s.setDate(18, piDataPrimVencimento);
				s.setString(19, piComitar);
			}

            public ResultSet getResult(CallableStatement statement) throws SQLException {
            	statusRetorno[0] = statement.getInt(12);
            	statusRetorno[1] = statement.getDate(13);
            	statusRetorno[2] = statement.getDate(14);
            	statusRetorno[3] = statement.getString(15);
				return TypeManager.readCursor(1, statement);
            }
		};
return TypeManager.readCursor(1, statement);
retorna uma Collection de Object que converto para o meu VO.

Valeu!

M

vc faz diferente de mim. Eu faço assim:

CallableStatement call = minhaConexao.prepareCall("{call minha_procedure(?, ?)}"); call.registerOutParameter("nome_do_parametro", Types.NUMERIC); call.setInt(1, 999); call.execute(); int retornoProcedure = call.getInt("nome_do_parametro");

acho muito mais facil.

[]'s

F

A FNC_SimulacaoContratacao retorna um cursor?
Senti falta do parameter número 1 ser registrado como OUT

F

Não cheguei a testar as últimas alternativas aqui propostas pois conversei com o desenvolvedor da PL (nos encontramos por acaso no cliente hoje e somos de empresas diferentes) e mencionei essa dificuldade. Identificamos que este parametro outs.registerOutParameter(12, java.sql.Types.INTEGER); estava com problema.

Parece que o mapeamento de Boolean entre Java e PL não funciona corretamente, por isso este parametro de número 12 era retornado como Integer, mas internamente para a PL ele era um Boolean (internamente é feita uma conversão de 0 para true e 1 para false ou o contrário). Mas o problema estava na maneira que a PL estava registrando/trabalhando com este parametro.

Ele arrumou do lado dele lá e tudo funcionou perfeito.

Obrigado a todos pelos palpites!!

Criado 13 de fevereiro de 2012
Ultima resposta 14 de fev. de 2012
Respostas 9
Participantes 4