Mybatis 在對 sql 語句進行預編譯之前,會對 sql 進行動態解析,解析爲一個 BoundSql 對象,也是在此處對動態 SQL 進行處理的。在動態 SQL 解析階段, #{ } 和 ${ } 會有不同的表現。
#{ } 解析爲一個 JDBC 預編譯語句(prepared statement)的參數標記符,即解析爲一個參數佔位符 ? 。
${ } 僅僅爲一個純碎的 string 替換,在動態 SQL 解析階段將會進行變量替換。
例如在mybatis的xml文件中,需要根據用戶名查詢用戶信息:
(1) 採用#{ }
select * from Admin where username = #{username }
解析爲:
select * from Admin where username = ?
(2)採用${ } ,假設傳進來的參數的值爲”Admin”
select * from Admin where username = ${username }
解析爲:
select * from Admin where username = 'Admin'
看似實現的效果是一樣的,但是某些情況下,兩者不能替換。
(1)當傳進去的參數爲表名時
採用#{ }
select * from #{table} where username = #{username }
解析爲:
select * from ? where username = ?
採用${ } ,假設傳入的表名爲”t_admin”,用戶名爲”Admin”
select * from ${table} where username = ${username }
解析爲:
select * from 't_admin' where username = 'Admin'
此時,sql語句編譯時將出現錯誤,因爲表名不能加單引號
同理,order by 後的參數,也不能用${ }來傳遞
(2)當傳進去的參數是sql語句時
採用#{ }
select * from Admin #{sql}
解析爲:
select * from Admin ?
此時的where條件是沒有用的
而採用${ } ,假設傳入的sql語句爲”where username = ‘Admin’ ”
select * from Admin ${sql}
解析爲:
select * from Admin where username = 'Admin'
則可以得到正確的結果
其中部分原理參照了博客:
http://blog.csdn.net/pfnie/article/details/53230994