← Назад к вопросам
Можно ли передавать параметры в CallableStatement?
2.0 Middle🔥 131 комментариев
#Другое
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Ответ на вопрос о параметрах в CallableStatement
Можно ли передавать параметры в CallableStatement?
Да, можно передавать параметры в CallableStatement несколькими способами. CallableStatement используется для вызова хранимых процедур в БД и поддерживает передачу параметров трёх типов: IN, OUT и INOUT.
Основные типы параметров
1. IN-параметры - передаём значения в хранимую процедуру
CallableStatement cs = connection.prepareCall("{call myProcedure(?)}");
cs.setString(1, "Hello"); // IN-параметр
cs.execute();
2. OUT-параметры - получаем результаты из процедуры
CallableStatement cs = connection.prepareCall("{call myProcedure(?)?}");
cs.registerOutParameter(2, java.sql.Types.INTEGER);
cs.setString(1, "Hello");
cs.execute();
int result = cs.getInt(2); // Получаем OUT-параметр
3. INOUT-параметры - передаём значение и получаем результат
CallableStatement cs = connection.prepareCall("{call processProcedure(?)}");
cs.setString(1, "input"); // IN часть
cs.registerOutParameter(1, java.sql.Types.VARCHAR); // OUT часть
cs.execute();
String result = cs.getString(1); // Получаем результат
Полный пример с IN-параметрами
public class CallableStatementExample {
public void callProcedureWithParameters(Connection conn) throws SQLException {
// Синтаксис: {call procedure_name(?, ?, ?)}
String sql = "{call calculateSum(?, ?, ?)}";
try (CallableStatement cs = conn.prepareCall(sql)) {
// Устанавливаем IN-параметры
cs.setInt(1, 10); // Первый параметр (IN)
cs.setInt(2, 20); // Второй параметр (IN)
cs.registerOutParameter(3, java.sql.Types.INTEGER); // Третий OUT
// Выполняем
cs.execute();
// Получаем результат
int result = cs.getInt(3);
System.out.println("Результат: " + result);
}
}
}
Передача различных типов данных
public void parameterTypes(Connection conn) throws SQLException {
String sql = "{call processData(?, ?, ?, ?, ?, ?)}";
try (CallableStatement cs = conn.prepareCall(sql)) {
// Целые числа
cs.setInt(1, 100); // int
cs.setLong(2, 9999999999L); // long
// Дробные числа
cs.setBigDecimal(3, new BigDecimal("99.99")); // BigDecimal
cs.setDouble(4, 3.14); // double
// Строки
cs.setString(5, "Hello World"); // String
// Даты
cs.setDate(6, java.sql.Date.valueOf("2024-03-22"));
cs.execute();
}
}
Передача с OUT-параметрами
public void callProcedureWithOutput(Connection conn) throws SQLException {
String sql = "{call getOrderInfo(?, ?, ?, ?)}";
try (CallableStatement cs = conn.prepareCall(sql)) {
// IN-параметры
cs.setInt(1, 12345); // orderId
// OUT-параметры (регистрируем перед выполнением)
cs.registerOutParameter(2, java.sql.Types.VARCHAR); // orderStatus
cs.registerOutParameter(3, java.sql.Types.DECIMAL); // orderTotal
cs.registerOutParameter(4, java.sql.Types.VARCHAR); // customerName
// Выполняем процедуру
cs.execute();
// Получаем результаты
String status = cs.getString(2);
BigDecimal total = cs.getBigDecimal(3);
String customer = cs.getString(4);
System.out.println("Статус: " + status);
System.out.println("Сумма: " + total);
System.out.println("Клиент: " + customer);
}
}
Именованные параметры (современный подход)
public void namedParameters(Connection conn) throws SQLException {
// Если БД поддерживает именованные параметры
String sql = "{call updateUser(firstName => ?, lastName => ?, age => ?)}";
try (CallableStatement cs = conn.prepareCall(sql)) {
cs.setString("firstName", "John");
cs.setString("lastName", "Doe");
cs.setInt("age", 30);
cs.execute();
}
}
Обработка результирующих наборов
public void getResultSet(Connection conn) throws SQLException {
String sql = "{call getEmployees(?, ?)}";
try (CallableStatement cs = conn.prepareCall(sql)) {
cs.setInt(1, 2024); // IN-параметр (год)
cs.registerOutParameter(2, java.sql.Types.INTEGER); // OUT
cs.execute();
// Обработка результирующего набора
try (ResultSet rs = cs.getResultSet()) {
while (rs.next()) {
System.out.println("ID: " + rs.getInt("id"));
System.out.println("Name: " + rs.getString("name"));
System.out.println("Salary: " + rs.getBigDecimal("salary"));
}
}
// Получаем OUT-параметр
int totalCount = cs.getInt(2);
System.out.println("Всего сотрудников: " + totalCount);
}
}
Массивы и коллекции (если БД поддерживает)
public void arrayParameters(Connection conn) throws SQLException {
String sql = "{call processList(?)}";
try (CallableStatement cs = conn.prepareCall(sql)) {
// Если БД (например, Oracle) поддерживает массивы
Array sqlArray = conn.createArrayOf("VARCHAR",
new String[]{"item1", "item2", "item3"});
cs.setArray(1, sqlArray);
cs.execute();
sqlArray.free();
}
}
Обработка NULL значений
public void nullParameters(Connection conn) throws SQLException {
String sql = "{call process(?, ?, ?)}";
try (CallableStatement cs = conn.prepareCall(sql)) {
cs.setString(1, "data"); // Обычное значение
cs.setNull(2, java.sql.Types.VARCHAR); // Явно NULL
cs.setInt(3, 42);
cs.execute();
}
}
Проверка NULL в OUT-параметрах
public void checkNullOutput(Connection conn) throws SQLException {
String sql = "{call getOptionalValue(?)}";
try (CallableStatement cs = conn.prepareCall(sql)) {
cs.registerOutParameter(1, java.sql.Types.VARCHAR);
cs.execute();
// Проверяем был ли NULL
String value = cs.getString(1);
if (cs.wasNull()) {
System.out.println("Параметр был NULL");
} else {
System.out.println("Значение: " + value);
}
}
}
Лучшие практики
public class CallableStatementBestPractices {
// ✅ Правильно: используем try-with-resources
public void goodExample(Connection conn) throws SQLException {
try (CallableStatement cs = conn.prepareCall("{call proc(?)}")) {
cs.setString(1, "value");
cs.execute();
} // Автоматически закроется
}
// ❌ Неправильно: утечка ресурсов
public void badExample(Connection conn) throws SQLException {
CallableStatement cs = conn.prepareCall("{call proc(?)}");
cs.setString(1, "value");
cs.execute();
// cs не закрывается
}
// ✅ Параметризация защищает от SQL-injection
public void secureProcedure(Connection conn, String userInput) throws SQLException {
try (CallableStatement cs = conn.prepareCall("{call search(?)}" )) {
cs.setString(1, userInput); // Безопасно
cs.execute();
}
}
}
Различия между Statement типами
| Тип | Использование | Параметры |
|---|---|---|
| Statement | Обычный SQL | Нет |
| PreparedStatement | Параметризованный SQL | IN |
| CallableStatement | Хранимые процедуры | IN, OUT, INOUT |
Резюме
- Да, параметры передаются - несколькими способами (IN, OUT, INOUT)
- Синтаксис:
{call procedure_name(?, ?, ?)} - Установка:
setXxx()методы для IN-параметров - Получение результата:
registerOutParameter()иgetXxx()для OUT - Типы данных: поддерживает все стандартные Java/SQL типы
- Безопасность: параметризация защищает от SQL-injection
- Resource management: всегда используй try-with-resources