各位大佬光臨寒舍,希望各位能賞臉給個三連,謝謝各位大佬了!!!??
目錄
1.有無預編譯
優點
缺點
2.SQL執行的快慢
3.能否被SQL注入
4.參數輸入方式
5.總結
1.有無預編譯
#{}是有預編譯的而${}是沒有預編譯的,那什么是預編譯,預編譯又有什么優缺點呢?在了解這個之前,預編譯進行的步驟:
它會將SQL語法進行解析再進行SQL優化再進行編譯,最后才給到數據庫進行執行。
優點
但是當有多個SQL語句的時候,預編譯就會顯得很慢,所以預編譯的SQL會被加入到一個緩存區,當只有?處的參數變化時,會直接從緩存區中拿到SQL,讓SQL進行執行,這樣它的速度就會加快很多。并且執行了SQL優化后,SQL語句就不會因為SQL注入導致數據庫被破壞。
缺點
在執行多個不僅僅是參數不同的SQL時每次都需要重新預編譯,導致速度不如不預編譯的快。
2.SQL執行的快慢
就像上面說的有無預編譯的區別,#{}在執行多個僅在參數有所不同的SQL時僅僅在預編譯時進行編譯省去了SQL的編譯,執行效率就更高,而${}則只是一個字符串拼接,每次都要把SQL語句給到數據庫進行編譯處理再執行,對于多個僅在參數有所不同的SQL時效率低,而在不僅僅是參數不同的SQL語句中${}更加有效率。但是當今的項目大部分都是執行多個僅在參數有所不同的SQL,所以大部分情況都是#{}更有效率。
3.能否被SQL注入
因為#{}在預編譯階段就進行了SQL的優化,導致它不僅僅是SQL的拼接,而是替換?處的參數,所以它不能被SQL注入從而使數據庫受到損害。而${}只是對數據的單純拼接,所以它是會被SQL注入的,就比如以下語句:
@Select("select * from student1 where id<=${id}")public List<StudentInfo> getId(Integer id) ;
我們可以直接輸入以下內容來獲取所有的用戶信息
1 or 1=1
也可以輸入以下內容直接刪除數據庫
1;drop database mybatis;
?所以${}是比較危險的。
4.參數輸入方式
#{}會根據所對應的參數選擇加不加“”,如String類型就會加“”,而Integer類型就不會加引號。而${}在所有情況下都不會加引號。如圖:
#{}會進行參數帶入
${}直接以字符形勢加入字符,這時候就會報錯,外面需要自己在參數外加‘’
所以在一般情況下#{}方便很多,我們不需要在參數為String時外面添加引號,但是也有特殊情況,那就是我們需要String類型但是我們不想加引號,如自己選定降序,升序排序。但是我們又怕SQL注入,所以一般對于這種情況我們都會對前端或者后端做出交互限制,讓前端發送數字,或者后端把前端的字符轉成數字,再以鍵值對的形式輸入參數,這樣就算有別的數據也會被判定為不合法。
5.總結
總的來說,#{}的用途更加廣泛,也更加安全,它們倆的區別概括一下也就三個點:
1.#{}有預編譯${}無預編譯
2.#{}寫入參數是占位的方式不會被SQL注入,安全,${}是直接以字符的形式寫入參數,會被SQL注入,不安全。
3.一般情況的SQL#{}都能完成,但是對于一些特殊場景比如排序,字段名作為參數等情況需要使用${},但是也要注意使用方法。
這里其實還有一個就是模糊查詢,正常情況下需要用${},因為例如say like?'%hi%',這樣的查詢我們只能用'%${hi}%',這樣的形式來注入參數,而剛好MySQL有個concat拼接字符串的函數,所以我們可以直接使用concat來完成如 say like concat('%',#{hi},'%')。那我們今天就講到這吧。有到時候和各位說再見了。在這之前:
制作不易,望各位大佬賞個臉,給個三連吧!!謝謝各位大佬了!!!