1. 程式人生 > >MyBatis面試題,'#{}與${}的區別'以及'sql預編譯'

MyBatis面試題,'#{}與${}的區別'以及'sql預編譯'

這個問題不算複雜,網上答案也比較”豐富”,
之所以寫這篇博文主要是以後查閱方便,自己總結也能加深印象,
畢竟它是面試題中的老相識,以後還要麻煩它關照關照…

MyBatis本身是基於JDBC封裝的.
動態sql,是其的強大特性之一.
且mybatis在預設情況下,是會對所有的sql進行預編譯的.

1. 什麼是#{},什麼是${}?

說區別之前,先來介紹一下#{}與${}

#{}會解析為一個JDBC預編譯語句的引數標記符;
簡單來說就是在你使用#{}的地方替換成一個引數佔位符’?’

${}就是一個簡單的字串替換;
替換這個特點也使得其也適合於一些特定的場景

總之,
#{} 就是編譯好SQL語句再取值.
${} 就是取值以後再去編譯SQL語句.

2. #{}和${}適合什麼樣的應用場景呢?

存在即合理
但是我的結論也是:能用#{}就儘量用.

#{}最明顯的優點就是防止sql注入
這是由於${}在預編譯之前就會被變數替換,這會存在sql注入問題

sql注入就是加入一些’破壞性語句’(從url、表單等入口),從而達到破壞網站內部的方法.
小朋友不要亂試,會被網站警告和記錄IP等資訊. 咦!?我咋知道…

網上說的最多的就是在’傳表名‘與‘動態排序‘等場景,應該使用${}
‘動態排序’先不提,
傳表名

‘不管是普通的#{}全表名傳遞還是#{}_user半表名傳遞(表名傳遞後面還要加上’_user’才算整個表名).我都用過#{}處理,不覺得有問題.

所以啊,我也不知道為啥網上都說’傳表名’用#{}會報錯之類的;
不知道是我看的資料都太老了沒更新,
還是我自己並未深入或者說使用並不規範,所以出現這種錯誤的理解.

3. sql預編譯沒有缺點?

好像真沒有?我是沒查到啊…
而且,sql預編譯有太多大神已經詳細解釋了,我就不重複造輪子了.

優點的話我就拾人牙慧,簡明扼要的列重點幾個:

1.預編譯階段可以優化sql執行
預編譯之後的sql多數情況下可以直接執行,DBMS不需要再次編譯,越複雜的sql,編譯的複雜度將越大,預編譯階段可以合併多次操作為一個操作.

2.提高執行效率(重複利用)
把一些格式固定的sql編譯後快取下來,當我們再次執行相同的sql語句時就不需要預編譯的過程了.

3.減少硬解析,可以節約CPU資源
軟解析,就是因為相同文字的sql語句存在於library cache中,所以本次sql語句的解析就可以去掉硬解析中的一個或多個步驟(主要為選擇執行計劃步驟),從而節省資源的耗費.