MyBatis中#{ }和${ }的區別
阿新 • • 發佈:2018-11-06
一、結論
#{ }:預編譯佔位符 ?,防止sql注入,會在引數兩端加上單引號 ' '
${ }:sql拼接符號,如表名必須用這個
#{ } 變數的替換是在 DBMS 中, ${ } 變數的替換階段是在動態 SQL解析階段
只要能夠使用#{ }解決的地方,我們都應該使用#{ }
二、細節
1、 #{ }
- 被解析為一個 JDBC 預編譯語句(prepared statement)的引數佔位符 ? 會在引數兩端加上單引號 ' ' ;
- 防止注入式攻擊,所以只要能夠使用#{ }解決的地方,我們都應該使用#{ }
select * from user where name = #{name}; select * from user where name = ?; select * from user where name = ${name}; select * from user where name = 'Joyce';
2.${ }
- 是單純的字串拼接,拼接完成後才會對SQL進行編譯、執行,所以效能較低 ,且不能複用
- 由於表名不能加單引號,所以不能使用#{ }。這時候就需要使用${ }來進行字串拼接。
${ } 在預編譯之前已經被變數替換了,這會存在 sql 注入問題。例如:
select * from ${tableName} where name = #{name}
假如,我們的引數 tableName 為" user; delete user; -- ",那麼 SQL 動態解析階段之後,預編譯之前的 sql 將變為:
select * from user; delete user; -- where name = ?;
--之後的語句被註釋掉,而原本查詢使用者的語句變成了查詢所有使用者資訊+刪除使用者表的語句,會對資料庫造成重大損傷。
重要:接受從使用者輸出的內容並提供給語句中不變的字串,這樣做是不安全的。這會導致潛在的SQL注入攻擊,因此你不應該允許使用者輸入這些欄位,或者通常自行轉義並檢查