1. 程式人生 > >iBatis 和 myBatis中 的“$”符號和“#”

iBatis 和 myBatis中 的“$”符號和“#”

一、iBatis中的$和#

在iBatis中使用sqlmap查詢時引用引數往往會使用 一對$或者#寫在引數前後,以此來區別原生sql和引數的區別;那麼#和$有什麼區別呢?什麼時候用#什麼時候又用$呢?這裡就這點和大家分享下:

簡單來說:

#可以進行與編譯,進行型別匹配,而$不進行資料型別匹配;
例如:
select * from table where id = #id# ,其中如果欄位id為字元型,那麼#id#表示的就是'id'型別,如果id為整型,那麼#id#就是id型別。 

select * from table where id = $id$ ,如果欄位id為整型,Sql語句就不會出錯,但是如果欄位id為字元型,那麼Sql語句應該寫成 select * from table where id = '$id$'注意這裡有引號
); 其實很明顯了:
$ 的作用實際上是字串拼接, 
select * from $tableName$ 
等效於 
StringBuffer sb = new StringBuffer(256); 
sb.append("select * from ").append(tableName); 
sb.toString();
#用於變數替換 
select * from table where id = #id# 
等效於 
prepareStement = stmt.createPrepareStement("select * from table where id = ?") 
prepareStement.setString(1,'abc');
什麼時候用$,什麼時候 用 # ?
對於變數部分, 應當使用#, 這樣可以有效的防止sql注入,# 都是用到了prepareStement,這樣對效率也有一定的提升 $只是簡單的字元拼接而已,對於非變數部分, 那隻能使用$, 實際上, 在很多場合,$也是有很多實際意義的 ;
例如 :
select * from $tableName$ (對於不同的表執行統一的查詢 )update $tableName$ set status = #status# (每個實體一張表,改變不同實體的狀態 )
特別提醒一下, $只是字串拼接, 所以要特別小心sql注入問題
什麼時候用$,什麼時候 用 # 

對於變數部分, 應當使用#, 這樣可以有效的防止sql注入, 未來,# 都是用到了prepareStement,這樣對效率也有一定的提升 


$只是簡單的字元拼接而已,對於非變數部分, 那隻能使用$, 實際上, 在很多場合,$也是有很多實際意義的 
例如 
select * from $tableName$ 對於不同的表執行統一的查詢 
update $tableName$ set status = #status# 每個實體一張表,改變不用實體的狀態 
特別提醒一下, $只是字串拼接, 所以要特別小心sql注入問題。

二:MyBatis中的$和#

1. #將傳入的資料都當成一個字串,會對傳入的資料加一個雙引號。

     如:order by #user_id#,如果傳入的值是666,那麼解析成sql時的值為order by "666", 如果傳入的值是id,則解析成的sql為order by "id";
2. $將傳入的資料直接顯示生成在sql中,不會有額外操作。

     如:order by $user_id$,如果傳入的值是111,那麼解析成sql時的值為order by user_id,  如果傳入的值是id,則解析成的sql為order by id.
3. #方式能夠很大程度防止sql注入。(後續部落格中會說明);
4.$方式無法防止Sql注入。(後續會有更新說明)
5.$方式一般用於傳入資料庫物件,例如傳入表名.
6.一般能用#的就別用$.MyBatis排序時使用order by 動態引數時需要注意,用$而不是#字串替換
預設情況下,使用#{}格式的語法會導致MyBatis建立預處理語句屬性並以它為背景設定安全的值(比如?)。這樣做很安全,很迅速也是首選做法,有時你只是想直接在SQL語句中插入一個不改變的字串。比如,像ORDER BY,你可以這樣來使用:
ORDER BY ${columnName}
這裡MyBatis不會修改或轉義字串。

重要:接受從使用者輸出的內容並提供給語句中不變的字串,這樣做是不安全的。這會導致潛在的SQL注入攻擊,因此你不應該允許使用者輸入這些欄位,或者通常自行轉義並檢查;

今天分享就到此,歡迎指正交流;