在開發中使用Mybatis常用到#{}與${},依舊有不少開發者對兩者的使用不是很清晰,正所謂好記性不如爛筆頭,特此總結一下。javascript
在mybatis中動態 sql 是其主要特性之一,在 mapper 中定義的參數傳到 xml 中以後,在執行操做以前 mybatis 會對其進行動態解析。mybatis 提供了兩種支持動態 sql 的語法:#{} 以及 $ {},其最大的區別則是#{}方式可以很大程度防止sql注入(安全),${}方式沒法防止Sql注入。什麼??不懂什麼是Sql注入?額。。。Sql注入指的是程序解析時會將你傳入的參數做爲原來SQL語句的一部分,打亂原來SQL的結構,而一般咱們只是須要傳入一個參數而已.java
什麼?還不懂SQL注入,我湖了QAQ。。。那就來個最簡單的例子:通常開發,確定是在前臺有兩個輸入框,一個用戶名,一個密碼,會在後臺裏,讀取前臺傳入的這兩個參數,拼成一段SQL,例如: select count(1) from tab where usesr=userinput and pass = passinput,把這段SQL鏈接數據後,看這個用戶名/密碼是否存在,若是存在的話,就能夠登錄成功了,若是不存在,就報一個登錄失敗的錯誤。對吧。
可是有這樣的狀況,這段SQL是根據用戶輸入拼出來,若是用戶故意輸入可讓後臺解析失敗的字符串,這就是SQL注入,例如,用戶在輸入密碼的時候,輸入 '''' ' or 1=1'', 這樣,後臺的程序在解析的時候,拼成的SQL語句,多是這樣的: select count(1) from tab where user=userinput and pass='' or 1=1; 看這條語句,能夠知道,在解析以後,用戶沒有輸入密碼,加了一個恆等的條件 1=1,這樣,這段SQL執行的時候,返回的 count值確定大於1的,若是程序的邏輯沒加過多的判斷,這樣就可以使用用戶名 userinput登錄,而不須要密碼。
防止SQL注入,首先要對密碼輸入中的單引號進行過濾,再在後面加其它的邏輯判斷,或者不用這樣的動態SQL拼sql
一、#{}表示一個佔位符號 至關於
jdbc
中的 ? 符號
#{}實現的是向prepareStatement中的預處理語句中設置參數值,sql語句中#{}表示一個佔位符即?安全
二、#{}將傳入的數據都當成一個字符串,會對自動傳入的數據加一個雙引號。如:
select * from user where id= #{user_id}
,若是傳入的值是11,那麼解析成sql時的值爲where id="11"
,mybatis
三、若是sql語句中只有
一個參數
,此時參數名稱能夠隨意定義
若是sql語句有多個參數,此時參數名稱應該是與當前表關聯[實體類的屬性名]或則[Map集合關鍵字],不能隨便寫,必須對應!以下圖app
一、$ {}將傳入的數據直接顯示生成在sql中。如:
select * from user where id= $ {user_id}
,若是傳入的值是11,那麼解析成sql時的值爲where id=11
測試
二、
$ {value}
中value
值有限制只能寫對應的value值不能隨便寫,由於${}
不會自動進行jdbc類型轉換code
三、簡單來講,在
JDBC
不支持使用佔位符的地方,均可以使用${}
xml
簡單來講區別就是對象
#{}方式可以很大程度防止sql注入(安全),${}方式沒法防止Sql注入
在
JDBC
能使用佔位符的地方,最好優先使用#{}
在
JDBC
不支持使用佔位符的地方,就只能使用${}
,典型狀況就是 動態參數
好比 有兩張表,分別是emp_2017
和 emp_2018
.若是須要在查詢語句中 動態指定表名,就只能使用${}
<select> select * from emp_ ${year} <select>
再好比MyBatis 排序時使用order by
動態參數時,此時也只能使用${}
<select> select * from dept order by ${name} </select>
通常# {}與$ {}用的比較多的地方是模糊查詢方面,因此下面來一個模糊查詢的案例
一、映射文件
在User.xml配置文件中添加以下內容:
<!-- 若是返回多個結果,mybatis會自動把返回的結果放在list容器中 --> <!-- resultType的配置和返回一個結果的配置同樣 --> <select id="queryUserByUsername1" parameterType="string" resultType="cn.itcast.mybatis.pojo.User"> SELECT * FROM `user` WHERE username LIKE #{username} </select>
二、測試程序
MybatisTest中添加測試方法以下:
@Test public void testQueryUserByUsername1() throws Exception { // 4. 建立SqlSession對象 SqlSession sqlSession = sqlSessionFactory.openSession(); // 5. 執行SqlSession對象執行查詢,獲取結果User // 查詢多條數據使用selectList方法 List<Object> list = sqlSession.selectList("queryUserByUsername1", "%王%"); // 6. 打印結果 for (Object user : list) { System.out.println(user); } // 7. 釋放資源 sqlSession.close(); }
測試效果以下圖:
一、映射文件:
在User.xml配置文件中添加以下內容:
<!-- 若是傳入的參數是簡單數據類型,${}裏面必須寫value --> <select id="queryUserByUsername2" parameterType="string" resultType="cn.itcast.mybatis.pojo.User"> SELECT * FROM `user` WHERE username LIKE '%${value}%' </select>
2.測試程序:
MybatisTest中添加測試方法以下:
@Test public void testQueryUserByUsername2() throws Exception { // 4. 建立SqlSession對象 SqlSession sqlSession = sqlSessionFactory.openSession(); // 5. 執行SqlSession對象執行查詢,獲取結果User // 查詢多條數據使用selectList方法 List<Object> list = sqlSession.selectList("queryUserByUsername2", "王"); // 6. 打印結果 for (Object user : list) { System.out.println(user); } // 7. 釋放資源 sqlSession.close(); }
固然兩個案例效果一致!
若是本文對你有一點點幫助,那麼請點個讚唄,謝謝~
最後,如有不足或者不正之處,歡迎指正批評,感激涕零!若是有疑問歡迎留言,絕對第一時間回覆!
歡迎各位關注個人公衆號,一塊兒探討技術,嚮往技術,追求技術,說好了來了就是盆友喔...