java 40 lines · 7 steps

Safe parameterized JDBC queries in Java

A JDBC query that filters users by email domain, guarding against both SQL injection and LIKE-pattern injection.

Explained by highlit
1public List<User> findUsersByEmailDomain(String domain, int minAge) {
2 String sql = """
3 SELECT id, username, email, age, created_at
4 FROM users
5 WHERE email LIKE ?
6 AND age >= ?
7 AND active = TRUE
8 ORDER BY created_at DESC
9 LIMIT ?
10 """;
11 
12 List<User> results = new ArrayList<>();
13 
14 try (Connection conn = dataSource.getConnection();
15 PreparedStatement stmt = conn.prepareStatement(sql)) {
16 
17 String escaped = domain.replace("!", "!!")
18 .replace("%", "!%")
19 .replace("_", "!_");
20 stmt.setString(1, "%@" + escaped);
21 stmt.setInt(2, minAge);
22 stmt.setInt(3, MAX_RESULTS);
23 
24 try (ResultSet rs = stmt.executeQuery()) {
25 while (rs.next()) {
26 User user = new User();
27 user.setId(rs.getLong("id"));
28 user.setUsername(rs.getString("username"));
29 user.setEmail(rs.getString("email"));
30 user.setAge(rs.getInt("age"));
31 user.setCreatedAt(rs.getTimestamp("created_at").toInstant());
32 results.add(user);
33 }
34 }
35 } catch (SQLException e) {
36 throw new DataAccessException("Failed to query users by domain: " + domain, e);
37 }
38 
39 return results;
40}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Prepared statements with placeholders keep user input out of the SQL text, closing the injection door.
  2. 2LIKE patterns need a second escaping pass because % and _ are wildcards even inside a parameter.
  3. 3Try-with-resources on connections, statements, and result sets guarantees cleanup even when queries throw.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Safe parameterized JDBC queries in Java — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code