1. 程式人生 > >MyBatis中#{ }和${ }的區別

MyBatis中#{ }和${ }的區別

一、結論

#{ }:預編譯佔位符 ?,防止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注入攻擊,因此你不應該允許使用者輸入這些欄位,或者通常自行轉義並檢查