推荐答案
在 MyBatis 中,#{} 和 ${} 是两种不同的参数占位符,它们的主要区别如下:
#{}:用于预编译 SQL 语句,能够有效防止 SQL 注入。MyBatis 会将#{}中的内容替换为?,并通过 PreparedStatement 进行参数绑定。${}:用于直接拼接 SQL 语句,不会进行预编译处理。MyBatis 会将${}中的内容直接替换为字符串,可能会导致 SQL 注入风险。
本题详细解读
1. #{} 的使用场景与特点
- 预编译处理:
#{}会将参数值通过PreparedStatement进行预编译处理,生成带有?占位符的 SQL 语句。这种方式可以有效防止 SQL 注入攻击。 - 参数类型处理:MyBatis 会根据参数的类型自动进行类型转换,例如将字符串类型的参数用单引号包裹。
- 安全性:由于使用了预编译,
#{}在处理用户输入时更加安全,适合处理动态 SQL 中的参数。
示例:
@Select("SELECT * FROM users WHERE id = #{userId}")
User selectUserById(@Param("userId") int userId);在这个例子中,#{userId} 会被替换为 ?,并通过 PreparedStatement 进行参数绑定。
2. ${} 的使用场景与特点
- 直接拼接:
${}会将参数值直接拼接到 SQL 语句中,不会进行预编译处理。这种方式适合用于动态 SQL 中的表名、列名等非参数部分。 - 无类型处理:
${}不会对参数进行类型转换,直接将参数值作为字符串拼接到 SQL 语句中。 - 潜在风险:由于直接拼接 SQL,
${}可能会导致 SQL 注入风险,尤其是在处理用户输入时。
示例:
@Select("SELECT * FROM ${tableName} WHERE id = #{userId}")
User selectUserFromTable(@Param("tableName") String tableName, @Param("userId") int userId);在这个例子中,${tableName} 会被直接替换为表名字符串,而 #{userId} 会被替换为 ? 并进行参数绑定。
3. 使用建议
- 优先使用
#{}:在大多数情况下,优先使用#{}来处理参数,以确保 SQL 语句的安全性和可维护性。 - 谨慎使用
${}:只有在需要动态拼接表名、列名等非参数部分时,才使用${},并且要确保输入的安全性,避免 SQL 注入风险。
通过理解 #{} 和 ${} 的区别,可以在 MyBatis 中更安全、更高效地编写 SQL 语句。