Ответ
Statement — это базовый интерфейс JDBC для выполнения статических SQL-запросов без параметров. Он создается из объекта Connection.
Основное использование и пример:
Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
Statement stmt = conn.createStatement();
// Для SELECT используем executeQuery()
String sqlQuery = "SELECT id, name FROM users WHERE status = 'active'";
ResultSet rs = stmt.executeQuery(sqlQuery);
while (rs.next()) {
System.out.println(rs.getInt("id") + ": " + rs.getString("name"));
}
// Для INSERT, UPDATE, DELETE используем executeUpdate()
String sqlUpdate = "UPDATE users SET status = 'inactive' WHERE last_login < '2023-01-01'";
int rowsAffected = stmt.executeUpdate(sqlUpdate);
System.out.println("Обновлено строк: " + rowsAffected);
// Всегда закрываем ресурсы!
rs.close();
stmt.close();
conn.close();
Критические недостатки и почему его избегают:
- Уязвимость к SQL-инъекциям: Запрос формируется конкатенацией строк, что позволяет злоумышленнику внедрить恶意 SQL-код.
// ОПАСНО! String userInput = "'; DROP TABLE users; --"; String sql = "SELECT * FROM users WHERE name = '" + userInput + "'"; stmt.executeQuery(sql); // Выполнит DROP TABLE! - Низкая производительность: Каждый запрос компилируется в СУБД заново, кеширование планов запросов неэффективно.
Когда использовать (редкие случаи):
- Выполнение DDL-операций (CREATE, ALTER, DROP).
- Выполнение простых, статистических запросов, где параметры известны на этапе компиляции и полностью контролируются разработчиком.
Рекомендация: Для любых запросов с данными, полученными от пользователя или извне, всегда используйте PreparedStatement, который защищает от инъекций и повышает производительность.
Ответ 18+ 🔞
Да ты посмотри, что за зверь такой — этот Statement! Ну, базовый интерфейс в JDBC, чтобы тупо, в лоб, SQL-запросы гонять. Без параметров, без ничего. Рождается он прямиком из Connection, как гриб после дождя.
Вот как его, голодранца, используют:
Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
Statement stmt = conn.createStatement();
// Для SELECT — executeQuery()
String sqlQuery = "SELECT id, name FROM users WHERE status = 'active'";
ResultSet rs = stmt.executeQuery(sqlQuery);
while (rs.next()) {
System.out.println(rs.getInt("id") + ": " + rs.getString("name"));
}
// Для INSERT, UPDATE, DELETE — executeUpdate()
String sqlUpdate = "UPDATE users SET status = 'inactive' WHERE last_login < '2023-01-01'";
int rowsAffected = stmt.executeUpdate(sqlUpdate);
System.out.println("Обновлено строк: " + rowsAffected);
// И не забудь всё прибить, а то память жрать будет!
rs.close();
stmt.close();
conn.close();
А теперь, блядь, главная причина, почему на него смотрят как на прокажённого:
- Уязвимость к SQL-инъекциям — это просто пиздец! Запрос склеивается из строк, как попало. Любой школьник с полпинка тебе всю базу угробит.
// ЭТО ПРЯМАЯ ДОРОГА В АД, НАХУЙ! String userInput = "'; DROP TABLE users; --"; String sql = "SELECT * FROM users WHERE name = '" + userInput + "'"; stmt.executeQuery(sql); // Ёбта, и таблицы users как не бывало! - Производительность — ниже плинтуса. Каждый раз, сука, запрос компилируется в СУБД с нуля. Планы выполнения не кешируются нормально, всё впустую.
Так когда же его, этого убогого, хоть куда-то можно пристроить?
- Ну, для DDL-команд — CREATE, ALTER, DROP. Там параметров обычно нет.
- Для каких-нибудь своих, внутренних, статических запросов, где все данные известны заранее и под контролем. Но это редкость, блядь.
Итог, как отче наш: Для любых запросов, куда попадают данные от пользователя или из внешнего мира — в рот меня чих-пых, забудь про Statement! Бери PreparedStatement. Он и от инъекций спасёт, и быстрее работать будет. Не будь мудаком, как тот Герасим, который всё по-своему, через жопу.