您好,登录后才能下订单哦!
密码登录
            
            
            
            
        登录注册
            
            
            
        点击 登录注册 即表示同意《亿速云用户服务条款》
        # MyBatis中的#{}和${}有什么区别
## 引言
在MyBatis框架中,`#{}`和`${}`是两种常见的参数占位符语法,它们在SQL语句中用于动态替换参数值。虽然表面上看功能相似,但底层实现机制、安全性和适用场景存在显著差异。本文将深入解析两者的区别,并通过代码示例帮助开发者正确选择和使用。
---
## 1. 核心机制对比
### 1.1 `#{}`(预编译占位符)
- **实现原理**  
  采用预编译(PreparedStatement)机制,运行时会被替换为`?`占位符,参数值通过JDBC的set方法安全注入。
- **示例代码**  
  ```xml
  <select id="findUserById" resultType="User">
    SELECT * FROM users WHERE id = #{userId}
  </select>
实际执行SQL:
  SELECT * FROM users WHERE id = ?
${}(字符串拼接)实现原理
直接进行字符串替换(Statement),参数值按原样拼接到SQL语句中。
示例代码
<select id="findUserByName" resultType="User">
SELECT * FROM users WHERE name = '${userName}'
</select>
若userName值为"John",最终SQL为:
SELECT * FROM users WHERE name = 'John'
| 特性 | #{} | 
${} | 
|---|---|---|
| SQL注入风险 | 安全(自动参数化) | 高风险(直接拼接) | 
| 预编译支持 | 是 | 否 | 
| 参数类型处理 | 自动类型转换(如Date→Timestamp) | 原样输出 | 
| 动态表名/列名 | 不支持 | 支持 | 
| 性能 | 通常更优(数据库可缓存执行计划) | 每次需重新解析SQL | 
<!-- 危险写法 -->
<select id="login" resultType="User">
  SELECT * FROM users 
  WHERE username = '${username}' AND password = '${password}'
</select>
攻击者输入:
username: admin' --
password: any
最终执行:
SELECT * FROM users WHERE username = 'admin' --' AND password = 'any'
<!-- 正确写法 -->
<select id="login" resultType="User">
  SELECT * FROM users 
  WHERE username = #{username} AND password = #{password}
</select>
#{}的情况${}的场景
<select id="queryByField" resultType="map">
 SELECT * FROM ${tableName} ORDER BY ${columnName}
</select>
<select id="findRecent" resultType="User">
 SELECT * FROM users 
 WHERE create_time > DATE_SUB(NOW(), INTERVAL ${days} DAY)
</select>
<select id="dynamicQuery" resultType="User">
  SELECT * FROM ${tablePrefix}_users
  WHERE status = #{status}
  <if test="orderBy != null">
    ORDER BY ${orderBy}
  </if>
</select>
通过自定义TypeHandler可增强#{}的处理能力:
@MappedTypes(JSONObject.class)
public class JsonTypeHandler extends BaseTypeHandler<JSONObject> {
  // 实现JSON与数据库字段的转换
}
| 选择原则 | 说明 | 
|---|---|
| 默认使用#{} | 保障安全性,预防SQL注入 | 
| ${}仅用于非值部分 | 表名、列名等元数据操作 | 
| 动态SQL优先用OGNL表达式 | <if>, <choose>等标签更安全 | 
正确理解这两种占位符的区别,能够帮助开发者在保证系统安全性的同时,灵活应对各种复杂SQL场景。 “`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。