Sobes.tech
Middle

Como chamar um procedimento armazenado em Java?

sobes.tech IA

Resposta da IA

Para chamar um procedimento armazenado em Java, utiliza-se CallableStatement do pacote java.sql.

Passos principais:

  1. Obter a conexão: Usa-se um objeto Connection.
    // Exemplo de obtenção de conexão (depende do driver e configuração)
    Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/mydatabase", "user", "password");
    
  2. Criar CallableStatement: A chamada SQL ao procedimento armazenado é passada ao construtor prepareCall(). A sintaxe depende do SGBD, mas geralmente tem a forma { call procedure_name(?, ?, ...) }.
    // Chamada de procedimento sem parâmetros
    CallableStatement cstmt = conn.prepareCall("{ call my_procedure() }");
    
    // Chamada de procedimento com parâmetros
    CallableStatement cstmtWithParams = conn.prepareCall("{ call my_procedure_with_params(?, ?) }");
    
  3. Definir os parâmetros de entrada: Se o procedimento aceita parâmetros, eles devem ser definidos usando os métodos setXxx(), onde Xxx corresponde ao tipo de dado (por exemplo, setString, setInt).
    // Definir parâmetros de entrada
    cstmtWithParams.setString(1, "value1");
    cstmtWithParams.setInt(2, 123);
    
  4. Registar os parâmetros de saída (se houver): Se o procedimento devolve valores através de parâmetros de saída, eles devem ser registados com registerOutParameter(), indicando o índice e o tipo de dado JDBC.
    // Procedimento com parâmetro de saída
    CallableStatement cstmtWithOut = conn.prepareCall("{ call my_procedure_with_out(?) }");
    cstmtWithOut.registerOutParameter(1, Types.VARCHAR); // VARCHAR como exemplo
    
  5. Executar a consulta: Usa-se o método execute(). Se o procedimento devolve um conjunto de resultados, pode-se usar executeQuery().
    // Executar procedimento
    cstmt.execute(); // Para procedimentos sem conjunto de resultados
    
    // Executar procedimento que devolve um conjunto de resultados
    // CallableStatement cstmtWithResultSet = conn.prepareCall("{ call get_data() }");
    // ResultSet rs = cstmtWithResultSet.executeQuery();
    
  6. Processar os resultados: Se o procedimento devolve um conjunto de resultados, pode-se processar como um ResultSet normal. Se houver parâmetros de saída, os seus valores são extraídos com métodos getXxx().
    // Processar parâmetro de saída
    String result = cstmtWithOut.getString(1);
    
    // Processar conjunto de resultados
    /*
    while (rs.next()) {
        // Ler dados do conjunto de resultados
    }
    rs.close();
    */
    
  7. Fechar recursos: É importante fechar CallableStatement e Connection. É recomendável usar blocos try-with-resources.
    // Fechamento de recursos usando try-with-resources
    try (Connection conn = DriverManager.getConnection("...", "...", "...")) {
        try (CallableStatement cstmt = conn.prepareCall("{ call my_procedure(?) }")) {
            cstmt.setString(1, "test");
            cstmt.execute();
            // Processar resultados
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }
    

Exemplo de chamada de procedimento com valor de entrada e valor retornado (via RETURN, e não um parâmetro OUT, característico no PostgreSQL/MySQL):

// Procedimento na base de dados: CREATE OR REPLACE FUNCTION add_numbers(a INT, b INT) RETURNS INT AS $$ BEGIN RETURN a + b; END; $$ LANGUAGE plpgsql;
try (Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/mydatabase", "user", "password")) {
    // Chamada de função SQL (frequentemente usa-se a sintaxe { ? = call function_name(?, ?) } para funções)
    try (CallableStatement cstmt = conn.prepareCall("{ ? = call add_numbers(?, ?) }")) {
        // Registar parâmetro de retorno
        cstmt.registerOutParameter(1, Types.INTEGER);
        // Definir parâmetros de entrada
        cstmt.setInt(2, 10);
        cstmt.setInt(3, 20);

        // Executar a chamada
        cstmt.execute();

        // Obter o resultado
        int sum = cstmt.getInt(1);
        System.out.println("Soma: " + sum); // Saída: Soma: 30
    }
} catch (SQLException e) {
    e.printStackTrace();
}

Diferenças entre CallableStatement e PreparedStatement:

Característica PreparedStatement CallableStatement
Propósito Executar consultas SQL parametrizadas Chamar procedimentos e funções armazenadas
Sintaxe Consulta SQL com ? Sintaxe dialetal de chamada ({ CALL ... })
Parâmetros de saída Não (apenas conjunto de resultados) Sim (via registerOutParameter)
Valor retornado Apenas conjunto de resultados (executeQuery) Pode ser via RETURN (como parâmetro OUT), conjunto de resultados

É necessário verificar a sintaxe de chamada de procedimentos/funções armazenadas ({ call ... } ou outro) e o suporte de tipos de dados JDBC (Types) para o SGBD específico utilizado.