1. 程式人生 > >MyBatis的sql對映檔案(傳參和陣列集合)

MyBatis的sql對映檔案(傳參和陣列集合)

 

一、sql對映檔案獲取引數個數

1、獲取單個引數寫法

      上篇文章CRUD操作以及使用過單個引數 

      Mybatis對於只有一個引數的情況下,不會做任何處理,我們對傳遞過來一個id值作為引數,xml檔案中就用#{id}來接收,因為只有一個引數實質上#{}裡可以是任何字串都可以,當然為了對應我們建議就用id(可讀性強)。

2、獲取多個引數的寫法

    多個引數的情況下,Mybatis會將引數封裝為一個Map物件,#{}其實內部是從這個Map物件中根據鍵獲取數值,

   介面實現類:

	/**
	 *  根據id和state查詢
	 * @param id
	 * @param state
	 * @return List<User>
	 */
	public List<User> selectUser(Integer id, Integer state);

    sql對映檔案

  1)引數1對應param1,引數2對應param2 ...  以此類推

	<select id="selectUser" resultType="cn.jq.mybatis.model.User">
		select * from t_user where id >= #{param1} and state = #{param2} 
	</select>

  2)引數1對應索引arg0,引數2對應索引arg1  ...  以此類推

	<select id="selectUser" resultType="cn.jq.mybatis.model.User">
		select * from t_user where id >= #{arg0} and state = #{arg1} 
	</select>

  3)在介面方法的引數上使用 @param(value) 註解,就可改變封裝的map物件的key值,就可以實現介面方法裡的引數名和xml檔案內接收引數名對應一致,可讀性強(推薦使用)

public List<User> selectUser(@Param("id")Integer id, @Param("state")Integer state);

	<select id="selectUser" resultType="cn.jq.mybatis.model.User">
		select * from t_user where id >= #{id} and state = #{state} 
	</select>

測試都ok

	List<User> userlist = userMapper.selectUser(3, 1);
	System.out.println(Arrays.asList(userlist));
----
[[User [id=3, username=li33, pazzword=li33qq, state=1, regDate=Tue Nov 13 09:38:55 CST 2018], User [id=14, username=李四, pazzword=123456, state=1, regDate=Tue Nov 13 09:38:55 CST 2018], User [id=17, username=李四, pazzword=123456, state=1, regDate=Tue Nov 13 16:06:33 CST 2018], User [id=18, username=李四, pazzword=123456, state=1, regDate=Tue Nov 13 16:06:58 CST 2018]]]

 4)Mybatis會把引數封裝成Map物件,我們就傳入一個Map物件,xml檔案裡獲取引數值就用#{Map的key值}:

如果查詢的資料不是model包裡的任何一個POJO?沒有對應的POJO,我們可以構造一個與引數對應的封裝物件,如分頁查詢

	public List<User> selectUser(Map<String, Object> map);

	<select id="selectUser" resultType="cn.jq.mybatis.model.User">
		select * from t_user where id >= #{id} and state = #{state} 
	</select>

			Map<String, Object> map = new HashMap<>();
			map.put("id", 3);
			map.put("state", 1);
			List<User> userlist = userMapper.selectUser(map);
			System.out.println(Arrays.asList(userlist));

 

二、sql對映檔案獲取引數的型別是集合或陣列

在Mybatis你還有一些特殊處理的引數型別要特別注意:如果引數型別是集合Collection(List,Set)或者是陣列,Mybatis也會把這些型別的引數封裝在一個Map物件中傳遞到xml檔案,

1、集合型別(List,Set)的變數,xml取值的時map的key是 collection[index],List集合時也可使用 list[index]

	public List<User> selectUser(List<String> paramlist);

	<select id="selectUser" resultType="cn.jq.mybatis.model.User">
		select * from t_user where id >= #{collection[0]} and state = #{collection[1]} 
	</select>

			List<String> paramlist = new ArrayList<>();
			paramlist.add("3");
			paramlist.add("1");
			List<User> userlist = userMapper.selectUser(paramlist);
			System.out.println(Arrays.asList(userlist));

2、陣列型別map的key是 array[index]

	public List<User> selectUser(String[] strArr);

	<select id="selectUser" resultType="cn.jq.mybatis.model.User">
		select * from t_user where id >= #{array[0]} and state = #{array[1]} 
	</select>

			String[] strArr = {"3","1"};
			List<User> userlist = userMapper.selectUser(strArr);
			System.out.println(Arrays.asList(userlist));

 

三、sql對映檔案獲取引數的符號 #{} 和 ${} 的區別

  MyBatis中#{ }和${ }都可以用來動態傳遞引數

#{}  對應底層使用 jdbc 的 PreparedStatementd 物件來執行sql語句,在SQL中相當於一個引數佔位符“?”,用來補全預編譯語句。它補全預編譯語句時,可以理解為在此引數值兩端加了單引號。

${}  對應底層使用 jdbc 的 Statement 物件來執行sql語句,就是單純的字串拼接,拼接完成後才會對SQL進行編譯、執行,所以效能較低,也無法複用。但是在有些#{ }無法勝任的地方,還是會需要${ }來完成。

結論:

#{}  很大程度防止sql注入,提高系統安全,一般能用#的就別用$.

${}  無法防止Sql注入,特殊的情況下使用它,凡是原生的jdbc不能使用佔位符的地方,就只能使用它,因為PreparedStatementd中,可以用佔位符的地方之後,where條件語句的引數中,其他地方不能用,比如用表名稱,order by 排序欄位,這些地方是不能用?佔位符的

 

#{} 裡除了可以寫接收引數的名稱外,還可以設定javaType,jdbcType,mode,numericScale,resultMap,typeHandler,jdbcTypeName屬性。