Java面试题更新 2026-08-05

在 MyBatis 框架中,参数占位符 #{} 与字符串拼接符 ${} 在 SQL 预处理、安全性以及使用场景上有哪些不同?请结合实际开发案例说明各自的使用注意事项。

后端开发安全意识技术原理JavaMyBatis

考察说明

考查对 MyBatis 中参数占位符 #{} 和 ${} 的语义、安全差异及适用场景的理解。

回答思路

  1. 【回答框架 1】#{} 是预编译参数占位符,MyBatis 会将其解析为 PreparedStatement 的 ? 占位符,通过 setObject 方法设置参数值。这一过程由 JDBC 驱动完成,参数值不会被拼接到 SQL 字符串中,因此能有效防止 SQL 注入。常见用法包括传入查询条件值、插入数据等。
  2. 【回答框架 2】${} 是文本替换符,MyBatis 会直接将参数值替换到 SQL 字符串中,本质是字符串拼接。由于未经过预编译,参数值可能被篡改导致 SQL 注入风险。它通常用于动态表名、列名、排序字段等结构不固定的场景,因为这些结构不能作为预编译参数。
  3. 【回答框架 3】在功能上,#{} 会自动为字符串类型添加引号,并对特殊字符进行转义;而 ${} 不会添加引号,需要开发者手动处理。因此对于普通值,优先使用 #{};仅在必须使用动态 SQL 结构时采用 ${},且要严格校验参数值来源。
  4. 【回答框架 4】性能上 #{} 可享受 PreparedStatement 的预编译缓存,多个相同 SQL 的重复执行效率更高;而 ${} 每次都会生成新的 SQL 文本,无法充分复用。在安全与可维护性上,推荐使用 #{},除非有特殊需求。
  5. 【关键点 1】#{} 预编译可防止 SQL 注入,${} 文本替换存在注入风险。
  6. 【关键点 2】#{} 自动处理类型和引号,${} 不做任何处理。
  7. 【关键点 3】${} 用于表名、列名等结构,需保证参数可信。
  8. 【关键点 4】动态 SQL 拼接时应优先使用 #{},除非是结构字段。
  9. 【易错点 1】绝不能将用户输入直接用在 ${} 中,否则有严重安全漏洞。
  10. 【易错点 2】不要误以为 #{} 能处理所有场景,如动态表名必须用 ${}。
  11. 【易错点 3】使用 ${} 时若参数为字符串且未加引号,会导致 SQL 语法错误。