mybatis中${}、 #{}區(qū)別及應(yīng)用場景

動態(tài)sql是mybatis的主要特性之一。在mapper中定義的參數(shù)傳到xml中之后,在查詢之前mybatis會對其進(jìn)行動態(tài)解析。

mybatis提供了兩種支持動態(tài)sql的語法:#{} 、${}。

select * from t_user where username = '${username}';

select * from t_user where username = #{username};

username傳參一致的話,這兩種執(zhí)行的結(jié)果是一樣的,但是這兩種方式在動態(tài)sql解析階段的處理是不一樣的。

1、#{}

解析為一個JDBC預(yù)編譯語句(prepared statement)的參數(shù)標(biāo)記符,把參數(shù)部分用占位符?代替。動態(tài)解析為:

select * from t_user where username = ? ;

而傳入的參數(shù)將會經(jīng)過PreparedStatement方法的強(qiáng)制類型檢查和安全檢查等處理,最后作為一個合法的字符串傳入。

2、${}

這種方式只會做簡單的字符串替換,在動態(tài)SQL解析階段將會進(jìn)行變量替換,假如傳遞的參數(shù)為Alice,最終處理結(jié)果如下:

select * from t_user where username = 'Alice' ;

這樣在預(yù)編譯之前的sql語句已經(jīng)不包含變量了,因此可以看出${} 變量的替換階段是在動態(tài)SQL解析階段。

3、#{} ${}兩種方式對比

1)是否預(yù)防SQL注入

以上不同的處理方式可以看出,#{}預(yù)處理之后可以預(yù)防SQL注入;而${}在預(yù)編譯之前就已經(jīng)被替換,有被注入的風(fēng)險,如下例:

如果傳入的username 為 a' or '1=1,那么使用${}處理后直接替換字符串的sql就解析為:

select * from t_user where username = a' or '1=1' ;

這樣的話所有的用戶數(shù)據(jù)就被查出來了,這樣就屬于SQL注入。

如果使用#{},經(jīng)過sql動態(tài)解析和預(yù)編譯,會把單引號轉(zhuǎn)義為\'那么sql最終解析為:

select * from t_user where username = "a\' or \'1=1 ";//這樣會查不出任何數(shù)據(jù),有效阻止sql注入

有的業(yè)務(wù)場景經(jīng)常用到模糊查詢,也就是like處理,推薦使用以下處理方式:

t_user.username like #username#

java代碼里:

if?(!StringUtil.isEmpty(this.username))?{

table.setUsername("%"?+?this.username +?"%");

}

或者也可以使用數(shù)據(jù)庫函數(shù)進(jìn)行連接處理:

select? * from t_user u where username? like CONCAT('%', #username#, '%')

注意:以上就可以發(fā)現(xiàn)在某些特定場景下只能用${},比如order by 后的排序字段,表名、列名,因?yàn)樾枰鎿Q為不變的常量。如果表名中使用#{}的話,會變成如下:

select * from #{tablename}-->tablename傳參為t_user --->處理后變成 select * from 't_user',沒有這樣的表名,這樣的話就會報錯了,order by 同理。

2)性能考慮

因?yàn)轭A(yù)編譯語句對象可以重復(fù)利用,把一個sql預(yù)編譯后產(chǎn)生的PreparedStatement對象緩存下來,下次對于同一個sql,可以直接使用緩存的PreparedStatement對象,mybatis默認(rèn)情況下,對所有的sql進(jìn)行預(yù)編譯,這樣的話#{}的處理方式性能會相對高些。

總結(jié):

能使用#{}的時候盡量使用#{}

表名、order by的排序字段作為變量時,使用${}。

如果這篇文章對你有用的話,那就請拿起你高貴的手,輕輕的點(diǎn)擊喜歡吧,你喜歡我,我也喜歡你呀!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容