Statement Types
Once you have a Connection, JDBC gives you three different interfaces for actually running SQL
against it: Statement, PreparedStatement, and CallableStatement. They all
come from a Connection, but they differ in how they handle SQL text, parameters, and precompilation.
The Three Interfaces at a Glance
| Interface | Created with | Use it for |
|---|---|---|
Statement | conn.createStatement() | Plain, fixed SQL with no user-supplied parameters |
PreparedStatement | conn.prepareStatement(sql) | Parameterized SQL using ? placeholders — the default choice for almost everything |
CallableStatement | conn.prepareCall(sql) | Calling a stored procedure in the database |
Statement: Plain SQL, No Parameters
Statement just runs a SQL string as-is. It's fine for fixed queries with no external input, like a
one-off SELECT COUNT(*). The moment you need to insert a value that comes from a user — a form
field, a URL parameter, anything outside your control — Statement becomes dangerous.
Example: Statement (Safe Only Because Nothing Is User-Supplied)
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM users");
Statement's SQL by concatenating user input directly into the string — e.g. "SELECT * FROM users WHERE name = '" + userInput + "'" — an attacker can inject their own SQL and read or destroy data. Never concatenate untrusted input into a Statement.PreparedStatement: Parameterized and Precompiled
PreparedStatement takes SQL with ? placeholders instead of inline values. You bind
actual values to those placeholders separately with methods like setString(index, value) and
setInt(index, value). The driver sends the SQL and parameters to the database separately, so
user-supplied values can never be interpreted as SQL syntax — this closes off SQL injection entirely.
The database can also precompile the statement once and reuse the execution plan across calls.
Example: PreparedStatement With a Placeholder
PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM users WHERE name = ?");
pstmt.setString(1, "Sonu");
ResultSet rs = pstmt.executeQuery();
PreparedStatement every time you run SQL in JDBC. A full deep-dive on it is coming later in this track.CallableStatement: Calling Stored Procedures
CallableStatement is for invoking a stored procedure that already lives inside the database, using
SQL's {call procedure_name(?, ?)} escape syntax. It supports IN, OUT, and INOUT parameters for
procedures that return values through parameters rather than (or in addition to) a result set. A full
deep-dive on CallableStatement is also coming later in this track.
Example: CallableStatement Shape
CallableStatement cstmt = conn.prepareCall("{call getUserById(?)}");
cstmt.setInt(1, 42);
ResultSet rs = cstmt.executeQuery();
ResultSet.