在 MyBatis 映射文件中,#{ } 和 ${ } 是兩種常見的參數佔位符,但它們的行為截然不同。正確理解二者區別,對於防止 SQL 注入、動態構建查詢至關重要。
| 特性 | #{ } | ${ } |
|---|---|---|
| 參數處理方式 | 預編譯參數(PreparedStatement),自動加引號 | 直接字符串替換,不加引號 |
| SQL 注入防護 | 有效防禦 | 無防禦,極易注入 |
| 適用場景 | 值參數(WHERE 條件、INSERT 值等) | 數據庫對象名(表名、列名、ORDER BY 列) |
| 性能 | 可複用執行計劃,較快 | 每次重新解析,較慢 |
SELECT * FROM user WHERE id = #{userId}
若傳入 111,生成 SQL:SELECT * FROM user WHERE id = ?,參數綁定為 111。
ORDER BY ${columnName}
若傳入 create_time,生成 SQL:ORDER BY create_time,無參數綁定。
默認使用
#{ }會生成 PreparedStatement 參數佔位符(?),安全、快捷且為首選。只有當需要動態指定表名、列名或排序字段時,才應謹慎使用${ },並務必自行驗證輸入,防止 SQL 注入。
#{ } 處理所有業務數據參數。${ }。${ } 時,必須在應用層對輸入進行嚴格白名單校驗。${ } 中直接拼接用戶未經過濾的輸入。#{ } 是安全的參數綁定機制,${ } 是不安全的字符串模板替換。掌握二者邊界,是編寫健壯 MyBatis 映射的關鍵。