1. 程式人生 > 其它 >Mybatis中#{}和${}的區別是什麼?

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部落格_#{}和${}的區別