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

InterfaceCreated withUse it for
Statementconn.createStatement()Plain, fixed SQL with no user-supplied parameters
PreparedStatementconn.prepareStatement(sql)Parameterized SQL using ? placeholders — the default choice for almost everything
CallableStatementconn.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");
SQL injection warning: if you build a 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();
Default choice: unless you have a specific reason not to, reach for 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();
Next up: Head to SELECT Queries to see how to actually run a query and read data back from a ResultSet.