MyBatis中#{}和${}的不同和${}的妙用

突然意識到sql語句的獨特語義要和代碼分離,我們就不能夠在代碼中寫sql語句!!比如我要用${}在MyBatis的sql中拼接排序類型的時候,我就不能夠在Java代碼中直接寫參數字符串爲Order By哪兒個類型

#{}和${}的基本不同我就不想說了,這裏要說的是進一步對佔位符和字符拼接的字面語義的領悟!!

#{}和${}基本不同在這篇文章的最後有提到過

佔位符:佔位符就是在某個地方佔領一個位置,把它單獨作爲某個東西,比如這裏就是把它作爲 值。 
字符拼接:字符拼接就是簡單的對字符串拼接。沒有特殊的其它含義。

問題出現:

不知道大家有沒有想過一個問題

SELECT * FROM #{tableName} //有沒有想過??
  •  

上面我們已經說過了佔位符的意義就是作爲值的存在,所以如果作爲值的話,那麼發送的sql語句就是這樣的:

SELECT * FROM  ?
  •  

大家都知道MyBatis中這種sql語句是要經過預編譯的,雖然MyBatis並沒有真正的用上數據庫的預編譯功能(因爲數據庫的預編譯默認是關閉的。。。而且MyBatis底層也是使用PreparedStatement和Statement這兩個對象,大家可以參考我的一篇博客Presatement和Statement深入理解+MySQL的預編譯)。

大家都知道,帶問號的sql語句是要傳遞參數的,好!!假如!!我們傳入了參數user,那麼查詢語句就是這樣的:

SELECT * FROM  'user'
  •  

請問,這種sql語句能夠執行成功嗎??試試就知道了!!

這裏寫圖片描述

很明顯語法錯誤!!

那麼有什麼辦法能夠解決呢??

沒錯!!!${}能夠解決這個問題,${}的功能是直接進行字符串拼接。這也是爲什麼${}不能夠防止一般的sql注入攻擊。因爲它是拼接啊!!

這樣寫就行了:

SELECT * FROM ${tableName} //如果傳入基本類型如字符串時就要把tableName改爲value才能夠成功取值。
  •  

這裏寫圖片描述

普通sql注入過程:

SELECT * FROM user WHERE username like '' OR 'XX'='XX' OR ''
  • 1

當用戶輸入:

' OR 'XX'='XX' OR '
  • 1

這樣就出現問題了。。。

這裏寫圖片描述

最後總結下:


 
  1. 一般${}用在我們能夠確定值的地方,也就是我們程序員自己賦值的地方。

  2. 而#{}一般用在用戶輸入值的地方!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章