Databases 10 min read

Understanding the Difference Between ${} and #{} in MyBatis and Their Impact on SQL Injection

This article explains how MyBatis' ${} and #{} placeholders differ in SQL generation, demonstrates their usage with code examples, analyzes the SQL injection risks of ${} versus the safety of #{} through prepared statements, and provides practical guidelines for choosing the appropriate placeholder in various scenarios.

Java Architect Essentials
Java Architect Essentials
Java Architect Essentials
Understanding the Difference Between ${} and #{} in MyBatis and Their Impact on SQL Injection

MyBatis provides two placeholder syntaxes, ${} and #{}, which behave differently when constructing SQL statements.

1.1 Demonstration of ${} and #{}

Database table user contains sample data.

List<User> findByUsername(String username);
List<User> findByUsername2(String username);

Mapper XML using

#{}:
<!-- Using #{} -->
<select id="findByUsername" parameterType="java.lang.String" resultType="com.lscl.entity.User">
    select * from user where username like #{username}
</select>

<!-- Using ${} (value must be provided) -->
<select id="findByUsername2" parameterType="java.lang.String" resultType="com.lscl.entity.User">
    select * from user where username like '%${value}%'
</select>

Test code executes both queries and prints the results, confirming that both approaches can retrieve data.

1.2 SQL Injection Issue

The ${} syntax directly concatenates the supplied value into the SQL string, which can lead to injection attacks, whereas #{} uses a prepared‑statement placeholder that safely escapes characters.

// Vulnerable test
List<User> userList2 = userDao.findByUsername2(" aaa' or 1=1 -- ");

The generated SQL shows the injected condition, returning all rows.

1.3 Detailed Difference

#{}

acts like a JDBC ? placeholder, adding quotes and escaping special characters, preventing injection. ${} inserts the raw value, so no escaping occurs.

1.4 How #{ } Prevents Injection

Under the hood, MyBatis calls PreparedStatement.setString(), which examines each character and escapes dangerous ones (e.g., single quotes) before sending the query to MySQL.

public void setString(int parameterIndex, String x) throws SQLException {
    // ... checks for null, builds escaped string, sets bytes ...
}

Debugging with breakpoints shows the final parameter passed to MySQL is safely quoted, e.g., 'aaa\' or 1=1 --'.

1.5 Application Scenarios

#{}

should be used for ordinary condition values (WHERE clauses) because it prevents injection. ${} is useful when the value must become part of the SQL syntax itself, such as dynamic table names or column lists, but the developer must ensure the input is trusted.

1.6 Summary

#{} uses prepared statements, automatically adds quotes, and escapes dangerous characters, thus protecting against SQL injection. • ${} performs raw string substitution, which can introduce injection vulnerabilities if untrusted input is used. • Choose #{} for parameter values and reserve ${} for cases where the value must participate in SQL syntax and is guaranteed safe.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavadatabaseMyBatisORMSQL injection
Java Architect Essentials
Written by

Java Architect Essentials

Committed to sharing quality articles and tutorials to help Java programmers progress from junior to mid-level to senior architect. We curate high-quality learning resources, interview questions, videos, and projects from across the internet to help you systematically improve your Java architecture skills. Follow and reply '1024' to get Java programming resources. Learn together, grow together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.