兩個 符號都是取值的,但是他們的區別是什麼呢?
一:問題的由來?
最近在工作中有個點擊排序的功能調試了許久,終尋因,總結之。
需求是這樣的,頁面有個table,有一列的上下箭頭可點擊並排序。對於這種需求,我的mybatis.xml的sql配置寫成了如下:
<if test="map.ColumnNameSort!=null and map.ColumnNameSort!=''">
ORDER BY columnName #{map.ColumnNameSort}
</if>
ColumnNameSort即前端傳的排序方式,asc或者desc。
然後,預計它的輸出應該是類似於下面這樣的
ORDER BY columnName desc
但是,真正跑起來時,排序的效果一直沒出現,經常一番查找,發現是mybatis 的’#{}’傳值的問題,它將sql語句編譯成了如下
ORDER BY columnName 'desc' 或者 ORDER BY columnName 'asc'
這樣,desc或者asc就成了字符串而不是關鍵字,sql語句的意思是columnName的別名是desc或者asc,沒加排序關鍵字時默認是正序排序,成了如下
ORDER BY columnName "desc" asc 或者 ORDER BY columnName "asc" asc
排序沒效果的問題找到原因了,解決之,mybatis提供了另一種綁定參數的方式–${param},將sql配置改爲
ORDER BY columnName ${map.ColumnNameSort}
這樣一來,mybatis會直接將ColumnNameSort的值加入sql中,不會轉義。正確結果:
ORDER BY columnName desc
二:對比區別
對於mybatis中#和$綁定參數的區別做個總結,避免以後類似的問題發生。
-
#{}
將傳入的數據都當成一個字符串,會對自動傳入的數據加一個雙引號。如:order by #{id},如果傳入的值是111,那麼解析成sql時的值爲order by “111”, 如果傳入的值是id,則解析成的sql爲order by “id”。 -
${}
將傳入的數據直接顯示生成在sql中。如:order by
${id},如果傳入的值是111,那麼解析成sql時的值爲order by 111, 如果傳入的值是id,則解析成的sql爲order
by id。 -
#
方式能夠很大程度防止sql注入。 -
$
方式無法防止Sql注入。 -
$
方式一般用於傳入數據庫對象,例如傳入表名. -
一般能用#的就別用$.
在mybatis接口mapper文件中引用傳入的參數是通過#{param}或者${param}來使用的。
至於mybatisl中#{}和${}的區別其實很簡單,但是之前一直沒有理解清楚,網上一堆錯誤的理解。所以在這裏記錄一下
其實這個問題很簡單。
select * from t_user where name = #{param}
使用#{}就等於使用了PrepareStatement這種佔位符的形式。可以防止sql注入等等問題。
select count(*), from t_user group by ${param}
這種group by 字段 ,order by 字段,表名,字段名等沒法使用佔位符的就需要使用${}
這裏展開說一下關於PrepareStatement的好處。
數據庫有個功能叫綁定變量,就是針對一條sql預編譯生成多個執行計劃,如果只是參數改變的重複sql,綁定變量則會提高很大的性能。PrepareStatement就會使用數據庫的綁定變量的功能。
TIP:#{} preparement State 預處理 佔位符 防止sql 注入