Карта / JDBC / PreparedStatement

PreparedStatement

PreparedStatement — безопасная и более быстрая версия Statement, где параметры запроса передаются отдельно от текста SQL, а не вклеиваются в строку.

String sql = "SELECT * FROM users WHERE email = ? AND age > ?";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setString(1, "artur@mail.ru");   // первый ? — индексация с 1, не с 0!
stmt.setInt(2, 18);

ResultSet rs = stmt.executeQuery();

? — место, куда подставится значение. Главная причина использовать PreparedStatement вместо обычного Statement — защита от SQL-инъекций (подробный разбор — в теме «SQL-инъекции и защита»).

Копнуть глубже

PreparedStatement также быстрее при повторных вызовах. База компилирует план выполнения запроса один раз и переиспользует его при следующих вызовах с другими параметрами — не нужно заново разбирать структуру SQL-текста на каждый вызов, как с обычным Statement.

Для INSERT/UPDATE/DELETE используется executeUpdate(), а не executeQuery() (тот — только для SELECT):

PreparedStatement stmt = conn.prepareStatement("UPDATE users SET age = ? WHERE id = ?");
stmt.setInt(1, 26);
stmt.setInt(2, 1);
int rowsAffected = stmt.executeUpdate();   // вернёт, сколько строк изменилось

Batch — пакетная вставка для большого количества записей сразу, гораздо быстрее, чем по одной:

PreparedStatement stmt = conn.prepareStatement("INSERT INTO users (name) VALUES (?)");
for (String name : names) {
    stmt.setString(1, name);
    stmt.addBatch();           // добавить в пакет, не выполнять сразу
}
stmt.executeBatch();             // выполнить весь пакет одним обращением к базе
🎤 Закрыл тему, если можешь объяснить:
• как PreparedStatement защищает от SQL-инъекций;
• зачем нужен batch и почему он быстрее одиночных вставок (если дошёл до 2-го слоя).