# 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進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。