${}用于sql标识符动态拼接,仅限表名、列名、关键字等无法预编译的场景,且必须配合白名单校验或可信来源控制,否则将导致sql注入。

MyBatis 中的 ${} 用于字符串直接拼接,只在**无法用预编译(即 #{})实现的动态 SQL 结构部分**才必须使用——核心前提是:该位置不能是“值”,而是 SQL 语法中的**标识符(identifier)**,且已确保输入安全。
动态表名或分表场景
当业务按时间、租户或区域分表时(如 order_202608、user_tenant_a),表名本身是 SQL 关键语法成分,PreparedStatement 不支持参数化表名。
必须用 ${tablePrefix}_${month} 拼接,但传入前需白名单校验(例如正则 ^[a-zA-Z0-9_]+$)。
动态列名或字段名
比如通用查询接口允许前端指定排序字段:ORDER BY ${sortColumn} ${sortOrder},或动态 SELECT 某些非固定字段:SELECT ${columns} FROM user。
此时列名不能加引号,也不能走预编译;必须严格限制 sortColumn 只能是数据库中真实存在的字段名(建议从枚举或配置中心读取)。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
动态 SQL 关键字或语法片段
如自定义 GROUP BY 维度、HAVING 条件中的聚合字段、UNION 子句结构等,只要涉及 SQL 解析阶段就必须出现的词法单元,都属于此类。
例如:GROUP BY ${groupByField} 或 ${unionClause} —— 这些内容必须在 MyBatis 动态解析阶段就确定,不能延迟到数据库执行时绑定。
LIKE 模糊匹配中的通配符位置(慎用)
虽然 #{} 更安全,但若需把 % 写在 SQL 字符串内部(如 name LIKE '${name}%'),有时为简化逻辑会用 ${};不过更推荐用 CONCAT('%', #{name}) 或在 Java 层拼好再传参,避免绕过防护。
所有使用 ${} 的地方,都必须配套做输入合法性校验或来源可信控制。未经过滤直接拼接用户输入,等于主动打开 SQL 注入大门。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










