Hibernate / MyBatis Interview questions
What is the difference between #{} and ${} in MyBatis?
Both syntaxes substitute a value into a SQL statement, but they work through fundamentally different mechanisms with very different safety implications — a distinction that's one of the most commonly tested MyBatis interview topics for good reason.
| #{} | ${} |
| Compiled as a JDBC PreparedStatement placeholder (?). | Performs raw, literal string substitution before SQL parsing. |
| Safe from SQL injection by design. | Vulnerable to SQL injection if used with untrusted input. |
| Value is automatically type-converted and escaped. | No escaping; the raw string is inserted directly. |
| Cannot be used for identifiers like table/column names. | Necessary for dynamic identifiers, e.g. a table name chosen at runtime. |
#{} should be the default choice for essentially all actual data values — anything a user or caller supplies — while ${} is reserved specifically for the narrow cases where a value needs to become part of the SQL's structure itself, like a dynamically chosen table or column name, which a PreparedStatement placeholder fundamentally can't parameterize since JDBC placeholders only work for values, not identifiers.
Whenever ${} is genuinely necessary, the substituted value should come from a trusted, tightly controlled source (like a fixed enum of allowed table names) rather than directly from unsanitized user input, since MyBatis performs no injection protection on that path at all.
More Related questions...