Назад к вопросам
Middle
68
questionbank

Как вызвать хранимую процедуру в Java?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

Для вызова хранимой процедуры в Java используется CallableStatement из пакета java.sql.

Основные шаги:

  1. Получить соединение: Используется объект Connection.
    // Пример получения соединения (зависит от драйвера и конфигурации)
    Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/mydatabase", "user", "password");
    
  2. Создать CallableStatement: SQL-вызов хранимой процедуры передается в конструктор prepareCall(). Синтаксис вызова зависит от СУБД, но часто имеет вид { call procedure_name(?, ?, ...) }.
    // Вызов процедуры без параметров
    CallableStatement cstmt = conn.prepareCall("{ call my_procedure() }");
    
    // Вызов процедуры с параметрами
    CallableStatement cstmtWithParams = conn.prepareCall("{ call my_procedure_with_params(?, ?) }");
    
  3. Установить входные параметры: Если процедура принимает параметры, их нужно установить, используя методы setXxx(), где Xxx соответствует типу данных (например, setString, setInt).
    // Установка входных параметров
    cstmtWithParams.setString(1, "value1");
    cstmtWithParams.setInt(2, 123);
    
  4. Зарегистрировать выходные параметры (если есть): Если процедура возвращает значения через выходные параметры, их нужно зарегистрировать с помощью registerOutParameter(), указав индекс параметра и тип данных JDBC.
    // Процедура с выходным параметром
    CallableStatement cstmtWithOut = conn.prepareCall("{ call my_procedure_with_out(?) }");
    cstmtWithOut.registerOutParameter(1, Types.VARCHAR); // VARCHAR как пример
    
  5. Выполнить запрос: Используется метод execute(). Если процедура возвращает результирующий набор, можно использовать executeQuery().
    // Выполнение процедуры
    cstmt.execute(); // Для процедур без результирующего набора
    
    // Выполнение процедуры, возвращающей результирующий набор
    // CallableStatement cstmtWithResultSet = conn.prepareCall("{ call get_data() }");
    // ResultSet rs = cstmtWithResultSet.executeQuery();
    
  6. Обработать результаты: Если процедура возвращает результирующий набор, его можно обработать как обычный ResultSet. Если есть выходные параметры, их значения извлекаются методами getXxx().
    // Обработка выходного параметра
    String result = cstmtWithOut.getString(1);
    
    // Обработка результирующего набора
    /*
    while (rs.next()) {
        // Чтение данных из результирующего набора
    }
    rs.close();
    */
    
  7. Закрыть ресурсы: Важно закрыть CallableStatement и Connection. Лучше использовать блок try-with-resources.
    // Закрытие ресурсов с использованием try-with-resources
    try (Connection conn = DriverManager.getConnection("...", "...", "...")) {
        try (CallableStatement cstmt = conn.prepareCall("{ call my_procedure(?) }")) {
            cstmt.setString(1, "test");
            cstmt.execute();
            // Обработка результатов
        }
    } catch (SQLException e) {
        e.printStackTrace();
    }
    

Пример вызова процедуры с входными и возвращаемым значением (через RETURN, а не OUT-параметр, характерно для PostgreSQL/MySQL):

// Процедура в базе данных: 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")) {
    // SQL-вызов функции (часто используется синтаксис { ? = call function_name(?, ?) } для функций)
    try (CallableStatement cstmt = conn.prepareCall("{ ? = call add_numbers(?, ?) }")) {
        // Регистрация выходного параметра (возвращаемого значения)
        cstmt.registerOutParameter(1, Types.INTEGER);
        // Установка входных параметров
        cstmt.setInt(2, 10);
        cstmt.setInt(3, 20);

        // Выполнение вызова
        cstmt.execute();

        // Получение результата
        int sum = cstmt.getInt(1);
        System.out.println("Сумма: " + sum); // Вывод: Сумма: 30
    }
} catch (SQLException e) {
    e.printStackTrace();
}

Отличия CallableStatement от PreparedStatement:

Особенность PreparedStatement CallableStatement
Назначение Выполнение параметризованных SQL-запросов Вызов хранимых процедур и функций
Синтаксис SQL-запрос с ? Диалектный синтаксис вызова ({ CALL ... })
Выходные параметры Нет (только результирующий набор) Есть (через registerOutParameter)
Возвращаемое значение Только результирующий набор (executeQuery) Может быть через RETURN (как OUT-параметр), результирующий набор

Необходимо проверить синтаксис вызова хранимых процедур/функций ({ call ... } или другой) и поддержку типов данных JDBC (Types) для конкретной используемой СУБД.