Mybatis中#{}和${}的區別是什么?


動態 sql 是 MyBatis 的主要特性之一,在 mapper 中定義的參數傳到 xml 中之后,在查詢之前 MyBatis 會對其進行動態解析。MyBatis 為我們提供了兩種支持動態 sql 的語法:#{} 以及 ${}。

面試題:#{}和${}的區別是什么?

1)#{}是預編譯處理,$ {}是字符串替換

2)MyBatis在處理#{}時,會將SQL中的#{}替換為?號,使用PreparedStatement的set方法來賦值;MyBatis在處理 $ { } 時,就是把 ${ } 替換成變量的值。

3)使用 #{} 可以有效的防止SQL注入,提高系統安全性。

要理解記憶這個題目,我覺得要抓住兩點:

(1)$ 符號一般用來當作占位符,常使用Linux腳本的同學應該對此有更深的體會吧。既然是占位符,當然就是被用來替換的。知道了這點就能很容易區分$和#,從而不容易記錯了。

(2)預編譯的機制。預編譯是提前對SQL語句進行預編譯,而其后注入的參數將不會再進行SQL編譯。我們知道,SQL注入是發生在編譯的過程中,因為惡意注入了某些特殊字符,最后被編譯成了惡意的執行操作。而預編譯機制則可以很好的防止SQL注入。在某些特殊場合下只能用${},不能用#{}。例如:在使用排序時ORDER BY ${id},如果使用#{id},則會被解析成ORDER BY “id”,這顯然是一種錯誤的寫法。

示例講解

<select id="selectPerson" parameterType="int" resultType="hashmap">
  SELECT * FROM PERSON WHERE ID = #{id}
</select>

這個語句名為 selectPerson,接受一個 int(或 Integer)類型的參數,並返回一個 HashMap 類型的對象,其中的鍵是列名,值便是結果行中的對應值。

注意參數符號:#{id}

這就告訴 MyBatis 創建一個預處理語句(PreparedStatement)參數,在 JDBC 中,這樣的一個參數在 SQL 中會由一個“?”來標識,並被傳遞到一個新的預處理語句中,

// 近似的 JDBC 代碼,非 MyBatis 代碼...
String selectPerson = "SELECT * FROM PERSON WHERE ID = ?";
PreparedStatement ps = conn.prepareStatement(selectPerson);
ps.setInt(1,id);

以下內容是對上述知識的擴展和理解

1.防止惡義SQL語法注入實例

實例一

String sql = "select * from tb_name where name = '" + varname + "' and passwd = '" + varpasswd + "' ";

如果我們把['or'1'='1]作為varpasswd傳入進來.用戶名隨意,看看會成為什么?

select * from tb_name = 隨意' and passwd = ' ' or '1'='1';

因為'1'='1'肯定成立,所以可以任何通過驗證

實例二

select  *  from  ${tableName}  where name =  #{name}

在這個例子中,如果表名為

 user; delete user; --

則動態解析之后 sql 如下:

select * from user; delete user; -- where name = ?;

--之后的語句被注釋掉,而原本查詢用戶的語句變成了查詢所有用戶信息+刪除用戶表的語句,會對數據庫造成重大損傷,極大可能導致服務器宕機。

2.預編譯

定義:指的是數據庫驅動在發送 sql 語句和參數給 DBMS 之前對 sql 語句進行編譯,這樣 DBMS 執行 sql 時,就不需要重新編譯。

為什么需要預編譯?

JDBC 中使用對象 PreparedStatement 來抽象預編譯語句,使用預編譯

1)預編譯階段可以優化 sql 的執行

預編譯之后的 sql 多數情況下可以直接執行,DBMS 不需要再次編譯,越復雜的sql,編譯的復雜度將越大,預編譯階段可以合並多次操作為一個操作。

2)預編譯語句對象可以重復利用

把一個 sql 預編譯后產生的 PreparedStatement 對象緩存下來,下次對於同一個sql,可以直接使用這個緩存的 PreparedState 對象。

MyBatis 默認情況下,將對所有的 sql 進行預編譯

 3.MyBatis sql 動態解析

MyBatis 在調用 connection 進行 sql 預編譯之前,會對sql語句進行動態解析,動態解析主要包含如下的功能:

占位符的處理

動態sql的處理

參數類型校驗

4.DBMS和DB的關系

DBMS數據庫管理系統(databasemanagementsystem)是一種操縱和管理數據庫的大型軟件,是用於建立、使用和維護數據庫(DB)。它對數據庫進行統一的管理和控制,以保證數據庫的安全性和完整性。用戶通過DBMS訪問數據庫(DB)中的數據。

MySQL是一個關系型數據庫管理系統。

數據庫是“按照數據結構來組織、存儲和管理數據的倉庫”。是一個長期存儲在計算機內的、有組織的、有共享的、統一管理的數據集合。

ref:(15條消息) #{}與${}的區別_詩人密語-CSDN博客_#{}和${}的區別


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM