1. 底层处理机制不同#{}预编译占位符采用预处理的方式执行 SQL。它会将传入的参数替换为?占位符并在数据库端进行预编译。MyBatis 会根据参数的数据类型自动进行处理比如字符串类型会自动加上单引号数字类型则直接传入。${}字符串直接替换仅仅是在内存中进行纯粹的字符串拼接直接将参数原样输出到 SQL 语句中不会做任何类型的转换或自动添加引号。如果传入的是字符串且没有手动加单引号就会因为不符合 SQL 语法而报错。2.安全性不同最关键的区别#{}由于采用了预编译机制参数值会被当作纯粹的“数据”而不是“SQL 指令”来解析因此能够有效防止 SQL 注入攻击安全性极高。${}因为是直接拼接字符串如果用户传入了恶意的 SQL 关键字例如OR 11这些内容会被数据库当作合法的 SQL 指令执行从而改变原始 SQL 的逻辑存在极大的SQL 注入风险。3.使用场景不同#{}适用于绝大多数常规的数据传递场景如WHERE id #{id}、INSERT INTO user(name) VALUES(#{name})等。${}仅适用于需要动态生成 SQL 结构的特殊场景。比如你需要动态指定表名SELECT * FROM ${tableName}、动态排序字段或方向ORDER BY price ${sort}。因为这些是 SQL 命令或关键字如果用#{}加上单引号变成了字符串就会导致 SQL 语法错误。