Назад к вопросам
Middle
68
questionbank
Как вызвать хранимую процедуру в Java?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
Для вызова хранимой процедуры в Java используется CallableStatement из пакета java.sql.
Основные шаги:
- Получить соединение: Используется объект
Connection.// Пример получения соединения (зависит от драйвера и конфигурации) Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/mydatabase", "user", "password"); - Создать
CallableStatement: SQL-вызов хранимой процедуры передается в конструкторprepareCall(). Синтаксис вызова зависит от СУБД, но часто имеет вид{ call procedure_name(?, ?, ...) }.// Вызов процедуры без параметров CallableStatement cstmt = conn.prepareCall("{ call my_procedure() }"); // Вызов процедуры с параметрами CallableStatement cstmtWithParams = conn.prepareCall("{ call my_procedure_with_params(?, ?) }"); - Установить входные параметры: Если процедура принимает параметры, их нужно установить, используя методы
setXxx(), гдеXxxсоответствует типу данных (например,setString,setInt).// Установка входных параметров cstmtWithParams.setString(1, "value1"); cstmtWithParams.setInt(2, 123); - Зарегистрировать выходные параметры (если есть): Если процедура возвращает значения через выходные параметры, их нужно зарегистрировать с помощью
registerOutParameter(), указав индекс параметра и тип данных JDBC.// Процедура с выходным параметром CallableStatement cstmtWithOut = conn.prepareCall("{ call my_procedure_with_out(?) }"); cstmtWithOut.registerOutParameter(1, Types.VARCHAR); // VARCHAR как пример - Выполнить запрос: Используется метод
execute(). Если процедура возвращает результирующий набор, можно использоватьexecuteQuery().// Выполнение процедуры cstmt.execute(); // Для процедур без результирующего набора // Выполнение процедуры, возвращающей результирующий набор // CallableStatement cstmtWithResultSet = conn.prepareCall("{ call get_data() }"); // ResultSet rs = cstmtWithResultSet.executeQuery(); - Обработать результаты: Если процедура возвращает результирующий набор, его можно обработать как обычный
ResultSet. Если есть выходные параметры, их значения извлекаются методамиgetXxx().// Обработка выходного параметра String result = cstmtWithOut.getString(1); // Обработка результирующего набора /* while (rs.next()) { // Чтение данных из результирующего набора } rs.close(); */ - Закрыть ресурсы: Важно закрыть
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) для конкретной используемой СУБД.