В чем разница между видами Statement?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Разница между Statement, PreparedStatement и CallableStatement
В JDBC есть три типа объектов для выполнения SQL запросов. Каждый решает свою задачу и имеет разные характеристики по производительности и безопасности.
Statement
Основной и самый простой способ выполнения SQL запросов. SQL отправляется сразу в БД в виде строки.
public class StatementExample {
public static void main(String[] args) throws SQLException {
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/mydb", "user", "password"
);
Statement stmt = conn.createStatement();
String sql = "SELECT * FROM users WHERE age > 18";
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
System.out.println(rs.getString("name"));
}
rs.close();
stmt.close();
conn.close();
}
}
Характеристики Statement:
- Простота: минимальный код
- Уязвимость к SQL injection: опасно с пользовательскими данными
- Низкая производительность: нет переиспользования при повторных запросах
- Без параметров: SQL строка полностью готова
PreparedStatement
Предварительно компилируемый запрос с параметрами. БД парсит шаблон один раз, потом просто меняет параметры.
public class PreparedStatementExample {
public static void main(String[] args) throws SQLException {
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/mydb", "user", "password"
);
String sql = "SELECT * FROM users WHERE age > ? AND name = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, 18);
pstmt.setString(2, "John");
ResultSet rs = pstmt.executeQuery();
while (rs.next()) {
System.out.println(rs.getString("name"));
}
rs.close();
pstmt.close();
conn.close();
}
}
Характеристики PreparedStatement:
- Безопасность: защита от SQL injection через параметризацию
- Производительность: план запроса компилируется один раз
- Переиспользование: можно вызвать несколько раз с разными параметрами
- Типизированные параметры: setInt(), setString() и т.д.
- Batch операции: эффективная загрузка большого количества данных
Batch операции с PreparedStatement
public class BatchExample {
public static void main(String[] args) throws SQLException {
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/mydb", "user", "password"
);
String sql = "INSERT INTO users (name, age) VALUES (?, ?)";
PreparedStatement pstmt = conn.prepareStatement(sql);
for (int i = 0; i < 1000; i++) {
pstmt.setString(1, "User" + i);
pstmt.setInt(2, 20 + i % 50);
pstmt.addBatch();
}
int[] results = pstmt.executeBatch();
System.out.println("Вставлено записей: " + results.length);
pstmt.close();
conn.close();
}
}
CallableStatement
Для вызова хранимых процедур в БД. Может возвращать несколько результатов и выходные параметры.
public class CallableStatementExample {
public static void main(String[] args) throws SQLException {
Connection conn = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/mydb", "user", "password"
);
String sql = "{call get_user_count(?, ?)}"; CallableStatement cstmt = conn.prepareCall(sql);
cstmt.registerOutParameter(2, Types.INTEGER);
cstmt.setInt(1, 18);
cstmt.execute();
int count = cstmt.getInt(2);
System.out.println("Пользователей старше 18: " + count);
cstmt.close();
conn.close();
}
}
Сравнительная таблица
| Свойство | Statement | PreparedStatement | CallableStatement |
|---|---|---|---|
| Простота | Высокая | Средняя | Низкая |
| Безопасность | Низкая | Высокая | Высокая |
| Производительность | Низкая | Высокая | Зависит от БД |
| Переиспользование | Нет | Да | Да |
| Парсинг SQL | Каждый раз | Один раз | Один раз |
| Хранимые процедуры | Нет | Нет | Да |
Защита от SQL injection
PreparedStatement автоматически экранирует значения параметров, предотвращая инъекции. Statement уязвим при конкатенации строк.
В современной разработке используют ORM-фреймворки (Hibernate, JPA), но понимание различий между Statement типами остаётся критично.