Statement and PreparedStatement
Statement executes an already assembled SQL string
Statement can send SQL that has already been fully assembled as a string.
This can be acceptable for fixed utility commands, but inserting user values through string concatenation is dangerous and inconvenient.
try (Statement statement = connection.createStatement()) {
int updated = statement.executeUpdate(
"UPDATE users SET active = false WHERE last_login IS NULL");
System.out.println(updated);
}
executeUpdate() is used for commands that modify data or schema
and returns the number of affected rows. Queries that return rows use executeQuery().
PreparedStatement separates SQL from values
If a query contains data supplied by the program, PreparedStatement is usually the right choice.
The SQL contains ? parameter markers, while values are passed separately through setter methods.
Parameter numbering starts at 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"));
}
}
}
This way, email is passed as data instead of becoming part of the SQL text.
That is not only more convenient for types and repeated execution, but also protects against classic SQL injection,
which appears when user input is unsafely concatenated into a query.