Why MyBatis Interview Answers on SQL Injection Still Fail – A Deep Technical Dive
The article dissects MyBatis' mechanisms for preventing SQL injection, compares the safe #{ } syntax with the risky ${ } syntax, explains the underlying PreparedStatement workflow, and provides concrete best‑practice guidelines and code examples for secure usage.
MyBatis and SQL Injection: Safe vs. Dangerous Syntax
When interviewers ask "How does MyBatis prevent SQL injection?", the key is to distinguish between the two placeholder syntaxes:
Safe: #{} – uses JDBC PreparedStatement for parameter binding, preventing injection.
Dangerous: ${} – performs direct string replacement, vulnerable unless limited to structural elements with strict whitelist validation.
Why #{} Prevents Injection
MyBatis parses the mapper XML at startup, converting statements like:
<select id="selectUser" resultType="User">
SELECT * FROM users WHERE username = #{username}
</select>into a SQL template with a ? placeholder. At runtime it creates a PreparedStatement:
String sql = "SELECT * FROM users WHERE username = ?";
PreparedStatement ps = connection.prepareStatement(sql);
ps.setString(1, userInput); // user input never becomes part of the SQL structureThe database parses the statement before any parameter values are supplied, so malicious input like ' OR '1'='1 is treated as a plain string.
How ${} Works and Its Risks
Using ${username} results in direct text substitution:
<select id="selectUser" resultType="User">
SELECT * FROM users WHERE username = '${username}'
</select>which becomes:
String sql = "SELECT * FROM users WHERE username = '" + username + "'";
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(sql);Here the user input participates in SQL construction, allowing injection attacks.
Allowed Use Cases for ${}
Only structural elements that cannot be parameterized may use ${}, and they must be validated against a whitelist:
// Whitelist validation example for ORDER BY column
public String validateSortColumn(String column) {
Set<String> allowed = Set.of("id", "username", "created_time", "status");
if (!allowed.contains(column)) {
throw new IllegalArgumentException("Invalid sort column: " + column);
}
return column;
}Mapper usage:
<select id="selectUsersOrderBy" resultType="User">
SELECT * FROM users ORDER BY ${validatedColumn}
</select>MyBatis Internal Execution Flow
The full pipeline from mapper interface to JDBC execution is:
Parsing phase (startup) : XML/annotation SQL is parsed into a SqlSource that produces a BoundSql with ? placeholders.
Proxy interception : MapperProxy intercepts the mapper method call and delegates to MapperMethod.
Method encapsulation : MapperMethod prepares the execution command and passes it to SqlSession.
Session scheduling : SqlSession forwards to an Executor (default SimpleExecutor).
Statement preparation : StatementHandler (specifically PreparedStatementHandler) creates the real PreparedStatement using the SQL from BoundSql.
Parameter binding : ParameterHandler (usually DefaultParameterHandler) sets the parameters on the PreparedStatement via setXXX() methods.
This chain guarantees that data values never alter the SQL structure.
Design Philosophy
Safe defaults : Prefer #{} for all user‑provided values.
Separation of concerns : SQL structure (trusted) vs. parameter data (untrusted).
Flexibility with responsibility : ${} is allowed only for dynamic table names, column names, or ORDER BY fields, and must be combined with strict whitelist checks.
Best‑Practice Checklist
Always use #{} for user inputs.
Never allow raw user input in ${} without validation.
Apply whitelist validation for any dynamic structural element.
Enable static code analysis tools (e.g., SonarQube) to flag unsafe ${} usage.
Configure MyBatis logging to verify that SQL statements contain ? placeholders and that parameters are bound separately.
Grant the database account only the minimal required privileges (SELECT, INSERT, UPDATE, DELETE) and prohibit DDL commands.
Illustrative Diagram
By following these guidelines and understanding the underlying mechanisms, developers can confidently answer interview questions on MyBatis SQL injection prevention and build secure data‑access layers.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Tech Freedom Circle
Crazy Maker Circle (Tech Freedom Architecture Circle): a community of tech enthusiasts, experts, and high‑performance fans. Many top‑level masters, architects, and hobbyists have achieved tech freedom; another wave of go‑getters are hustling hard toward tech freedom.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
