[RESOLVIDO] Stored Procedures (Functions) do postgres no TopLink

Bem pessoal, primeiramente boa noite;

Sou bem novo no Java, mas estou aprendendo rápido, e sempre existe a primeira vez de postar uma dúvida no fórum não é mesmo!? Então acredito estar no lugar correto.
Bem, estou desenvolvendo uma aplicação que vai interagir muito com o banco, e estamos utilizando o PostgreSQL. Criei uma stored procedure (function) no banco que faz a leitura de uma tabela de produtos e lança em uma tabela de movimento determinados movimentos de acordo com alguns critérios que criei na própria function.

O problema pareceu simples de início, mas depois de três dias de intensas tentativas cheguei a conclusão que não consigo efetuar essa tarefa. Pesquisei documentação do TopLink, algumas classes como StoredFunctionCall, Query e seu método createNativeQuery, dentre outras do TopLink, mas todas sem sucesso. A maioria das tentativas me diziam que a minha instrução estava errada.

Gostaria de saber dos senhores se existe uma forma padrão para chamar stored procedures no JAVA, que estão especificamente no PostgreSQL, no formato de linguagem PL/PgSQL. Abaixo vai minha última tentativa frustrada, e o seu respectivo erro.

Desde já agradeço a atenção de todos!

package br.com.projeto2.bean;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Types;
import javax.swing.JOptionPane;

public class CallProcedure {

    public void storedProcedure() {
        try {
            String url = "jdbc:postgresql://Localhost:5432/banco_tcc";
            String usr = "postgres";
            String pas = "******";

            Class.forName("org.postgresql.Driver");
            Connection MinhaConexao = DriverManager.getConnection(url, usr, pas);

            MinhaConexao.setAutoCommit(false);

            CallableStatement proc = MinhaConexao.prepareCall("{? = popula_tb_movimento_estoque()}");
            
            proc.registerOutParameter(1, Types.INTEGER);

            proc.execute();
            proc.close();


        } catch (ClassNotFoundException ex) {
            System.out.println("Driver JDBC- nao encontrado");
        } catch (SQLException ex) {
            JOptionPane.showMessageDialog(null, "Nao houve Inclusao. Erro: " + ex.getMessage() + "", "Inclusão sem sucesso.", JOptionPane.ERROR_MESSAGE);
            ex.printStackTrace();
        }
    }
}

[color=red]Erro Gerado:[/color]

[EL Info]: 2012-08-24 20:23:03.687--ServerSession(7079781)--EclipseLink, version: Eclipse Persistence Services - 2.3.2.v20111125-r10461
[EL Info]: 2012-08-24 20:23:04.15--ServerSession(7079781)--file:/C:/Users/Holyspear/Documents/NetBeansProjects/projeto_TCC2/build/classes/_banco_tccPU login successful
org.postgresql.util.PSQLException: Malformed function or procedure escape syntax at offset 5.

De acordo com esta documentação
http://jdbc.postgresql.org/documentation/80/callproc.html

sua chamada à procedure deveria ser alterada para

CallableStatement proc = MinhaConexao.prepareCall("{? = call popula_tb_movimento_estoque()}");

Obrigado pela resposta Ademilton… já é um começo! Pelo menos não deu erro, porém… não executou nada no banco. Bem, eu alterei o código para o que segue:

            String url = "jdbc:postgresql://Localhost:5432/banco_tcc";
            String usr = "postgres";
            String pas = "abencoado";

            Class.forName("org.postgresql.Driver");
            Connection MinhaConexao = DriverManager.getConnection(url, usr, pas);

            MinhaConexao.setAutoCommit(false);
            
            CallableStatement proc = MinhaConexao.prepareCall("{ ? = call popula_tb_movimento_estoque() }");
            proc.registerOutParameter(1, Types.INTEGER);
            proc.execute();
            Integer results = (Integer) proc.getInt(1);
            proc.close();

O novo código não produziu o efeito esperado no Postgree. Na verdade não executou nada, nenhum efeito no banco, nenhum retorno. Para testes, eu construi a seguinte função:

CREATE OR REPLACE FUNCTION popula_tb_movimento_estoque()
  RETURNS integer AS
$BODY$
    DECLARE
        id_estoque      integer;
        id_produto      integer;
        tp_movimento    numeric(15,2);
        dt_movimento    numeric(12);
        qtd_movimentada numeric(15,2);
        produtos_view	record;
    
    BEGIN     
        
        FOR produtos_view IN SELECT p.id_produto FROM tb_produtos p
	LOOP
            
            INSERT INTO tb_movimento_estoque(tp_movimento, dt_movimento, qtd_movimentada, id_produto)
            VALUES ('E', '2012/08/01', 10, produtos_view.id_produto);
            
        END LOOP;
	
	RETURN 1;

    END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;
ALTER FUNCTION popula_tb_movimento_estoque()
  OWNER TO postgres;

Quem puder ajudar galera, eu agradeço desde já!
Abraços! :wink:

Não estaria faltando um commit dentro da sua procedure ?

Desculpem galera, mas já resolvi o problema!!!

Fica aqui para quem tiver problemas, pois foi bem complicado encontrar (talvez para outros iniciantes como eu seja de grande valia).

O que ocorreu é que eu configurei a seguinte linha:

 MinhaConexao.setAutoCommit(false);

Sendo que a minha conexão não “finalizava”, então eu setei para TRUE e a alteração no banco ocorreu!!!
Ao tentar incluir um commit na procedure, o Postgree não aceitou a cláusula e aconselhou outros métodos. Eu achei melhor controlar o commit pelo java mesmo, uma vez que abri uma conexão específica para essa ação.

Muito obrigado mesmo Ademilton, me ajudou bastante. Abraços amigo!