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是一個關係型資料庫管理系統。
資料庫是“按照資料結構來組織、儲存和管理資料的倉庫”。是一個長期儲存在計算機內的、有組織的、有共享的、統一管理的資料集合。