1、#{}將傳入的數據都當成一個字符串,會對自動傳入的數據加一個引號(單引號?雙引號?加了引號就對了)如:
//傳入的值是sex
order by #{column}
解析后為
order by “sex” //將會出錯
2、${}將傳入的數據直接顯示生成在sql中,如:
//傳入的值是sex order by ${column}
解析后為
order by sex //正確的
3、#{}可以在很大程度上防止sql注入,${}無法防止sql注入
4、${}一般用於傳入數據庫對象,例如傳入表名(mybatis動態查詢)
6、能用#就別用$
#使用了PreparedStatement來進行預處理,然后用set的方式對占位符進行設置;
$則是通過Statement直接進行查詢,當有參數時直接進行拼接進行查詢。(具體大家可以去看jdbc里面的PreparedStatement和Statement的處理方式不同)
mybatis在對SQL語句進行預編譯之前,會對SQL進行動態解析,#{}和${}會有不同的變現。
在下面的語句中,name值為zhangsan,下面兩種方式得到的結果沒有區別
1、select * from user where name = #{name}; 2、select * from user where name = ${name};
得到的解析后的結果均為
select * from user where name = 'zhangsan'
但是#{}在動態解析的時候,會把參數部分解析成一個占位符?代替
select * from user where name = #{name}; 動態解析為 select * from user where name = ?;
而${}則是簡單的字符替換,在動態解析階段,該sql會被解析成
select * from user where name = 'zhangsan';
以上,#{} 的參數替換是發生在 DBMS(數據庫管理系統) 中,而 ${} 則發生在動態解析過程中。
針對上面的sql,如果傳入的值是;drop table user;,
那么第一條用#{}的sql解析為:
select * from user where name = “;drop table user;” //查不到東西
那么第二條用${}的sql解析為:
select * from user where name = ;drop table user;//會出錯
傳入的應該name = lhh;drop table user;才對啊,要是name=;本來就會有錯;
這時候已經sql注入了。
優先使用 #{}。因為 ${} 會導致 sql 注入的問題。
若不得不使用“${xxx}”這樣的參數,要手工地做好過濾工作,來防止sql注入攻擊。