Statement и PreparedStatement
Statement выполняет готовую строку SQL
Statement умеет отправить базе SQL, который уже полностью собран строкой.
Для фиксированных служебных команд это возможно, но подставлять пользовательские значения через конкатенацию строк опасно и неудобно.
try (Statement statement = connection.createStatement()) {
int updated = statement.executeUpdate(
"UPDATE users SET active = false WHERE last_login IS NULL");
System.out.println(updated);
}
executeUpdate() используют для команд, которые изменяют данные или схему
и возвращают количество затронутых строк. Для запросов, возвращающих строки, применяется executeQuery().
PreparedStatement отделяет SQL от значений
Если в запросе есть данные, которые приходят из программы, обычно нужен PreparedStatement.
В SQL ставятся маркеры ?, а значения передаются отдельными setter-методами.
Нумерация параметров начинается с 1.
String sql = "SELECT id, name FROM users WHERE email = ?";
try (PreparedStatement statement = connection.prepareStatement(sql)) {
statement.setString(1, email);
try (ResultSet result = statement.executeQuery()) {
while (result.next()) {
System.out.println(result.getLong("id"));
}
}
}
Так значение email передаётся как данные, а не становится частью текста SQL.
Это не только удобнее для типов и повторного выполнения, но и защищает от классической SQL-инъекции,
которая возникает при небезопасной склейке пользовательского ввода с запросом.