1. 程式人生 > >【SSM-MyBatis框架】Mapper.xml配置檔案(mybatis的核心)

【SSM-MyBatis框架】Mapper.xml配置檔案(mybatis的核心)

  Mapper.xml對映檔案中定義了操作資料庫的sql,每一個sql是一個statement,對映檔案是myBatis的核心。

  1.輸入對映(ParameterType)

    通過parameterType指定輸入引數的型別,型別可以是簡單型別,pojo,包裝型別,hashmap。

    1.1 #{}與${}

     #{}實現向prepareStatement中的預處理語句中設定引數值,sql語句中#{}表示一個佔位符。

<select id="findUserById" parameterType="int"  resultType="User">
	SELECT * FROM USER WHERE id = #{value}
</select>

   使用佔位符可以防止sql的注入,在使用時不需要關心引數的型別,mybatis會自動的進行Java與jdbc的轉換。#{} 可以接受簡單型別和pojo的屬性值。如果parameterType中指定的是單個的簡單型別,#{}中可以使用value或是其他值。

  #{}與${}的不同:

   通過${}可以將parameterType傳入的內容拼接在sql中,並且不進行jdbc型別轉換,${}可以接受簡單型別和pojo的屬性值,若parameterType為單個簡單型別時,${}中必須使用value。使用${}不能防止sql注入,但有時會很方便,例如:

	<select id="findUserByUsername" parameterType="java.lang.String" resultType="User">
				SELECT * FROM USER WHERE username LIKE '%${value}%'
	</select>

再比如order by排序,如果將列名通過引數傳入sql,根據傳的列名進行排序,應該寫為:

ORDER BY${columnName}

如果使用#{}將無法實現此功能。

   1.2 傳遞包裝型別物件:

     開發中通過pojo傳遞查詢條件,查詢條件是綜合的查詢條件時,不僅包含使用者的查詢條件,而且包含其他的查詢條件,這時可以使用包裝物件型別傳遞引數。

     1. 定義包裝型別物件:

public class QueryVo {
	
	private User user;
	
	//自定義使用者擴充套件類
	private UserCustom userCustom;


    2.mapper.xml檔案:

<!-- 使用者資訊的綜合查詢	這是輸入對映傳遞pojo包裝類物件的測試
				UserQueryVo:就是UserCustom的包裝類,在其中也可以包裝其他類的物件
				 UserCustom:是User的擴充套件類-->
		<select id="findUserList" parameterType="queryVo" resultType="UserCustom">
			SELECT * FROM USER where user.sex=#{userCustom.sex} and user.username LIKE '%${userCustom.username}%'


		</select>		

    說明 :mybatis底層是通過ognl從pojo中獲取屬性值:#{userCustom.sex} ,userCustom即是傳入的pojo包裝物件的屬性值。 queryVo即是上面包裝物件的別名。

   1.3 傳遞HashMap:

     1.mapper.xml檔案:

<select id="findUserListHashmap" parameterType="hashmap" resultType="UserCustom">
	SELECT * FROM USER where user.sex=#{sex} AND user.username LIKE '%${name}%'


</select>	

  2.測試檔案:

public void findUserListHashmap() throws Exception {
		SqlSession session = sqlSessionFactory.openSession();
		
		//通過session自動建立mapper代理物件
		UserMapper userMap = session.getMapper(UserMapper.class);
		Map<String , Object> map = new HashMap<String, Object>();
		map.put("sex", "1");
		map.put("name","小明");
		List<UserCustom> list = userMap.findUserListHashmap(map);
		System.out.println(list);
	}


    2.輸出對映:(ResultType、ResultMap)

     2.1ResultType,輸出為簡單型別:

      1.mapper.xml檔案:

<!-- 輸出對映的測試,輸出一個簡單型別(查詢資料記錄總數) -->
		<select id="findCount"  parameterType="UserQueryVo" resultType="int">
			SELECT COUNT(*) FROM USER Where 
	        </select>


    輸出簡單型別時,必須查詢出來的結果集有一條記錄,最終將第一個欄位的值轉換為輸出型別。使用session中的selectOne可進行查詢單條記錄。

     2.2 ResultType,輸出為pojo型別:

    1.mapper.xml

(方法呼叫selectOne)

<select id="findUserById" parameterType="int"  resultType="User">
	SELECT * FROM USER WHERE id = #{value}
</select>

(方法呼叫selectList)

<select id="findUserById" parameterType="user"  resultType="User">
	SELECT * FROM USER WHERE name like '%${name}%'
</select>

    2.3  ResultType 總結:

輸出pojo物件和輸出pojo列表在sql中定義的resultType是一樣的。

返回單個pojo物件要保證sql查詢出來的結果集為單條,內部使用session.selectOne方法呼叫,mapper介面使用pojo物件作為方法返回值。

返回pojo列表表示查詢出來的結果集可能為多條,內部使用session.selectList方法,mapper介面使用List<pojo>物件作為方法返回值。

  2.4 輸出型別為hashMap:

 輸出型別可以改為hashMap,輸出的欄位名作為key,輸出的欄位值為value

  2.5 ResultMap(重點)

   ResultType可以指定pojo,將查詢結果對映成pojo的屬性。但是要求資料庫列名與pojo屬性名必須相同,才能對映成功。

   如過查詢的欄位名與pojo的屬性名不同,則通過resultMap,將欄位名和屬性名做一個對映,resultMap實質上,還是將資料庫欄位對映到pojo中。

    resultMap可以實現將查詢結果對映為複雜型別的pojo。如:在查詢結果對映物件中,包括pojo和list實現一對一和一對多的查詢。

      例子:

        實現下面一個sql的輸出結果的引數對映:

             select id,id_ ,name, name_ from user where id=#{id}

     User類中屬性名和上面查詢的列名不一樣。

    定義ResultMap:

<resultMap type="cn.edu.hpu.ssm.po.Orders" id="ordersMap">
				<id column="id" property="id"/>
				<result column="user_id" property="userId"/>
				<result column="number" property="number"/>
				<result column="createtime" property="createtime"/>
				<result column="note" property="note"/>
				
				<association property="user" javaType="cn.edu.hpu.ssm.po.User">
						<id column="user_id" property="id"/>
						<result column="username" property="username"/>
						<result column="sex" property="sex"/>
						<result column="address" property="address"/>
				</association>
</resultMap>

   ResultMap中引數的含義:

       type:定義對映的最終型別。  id:引用時的標識

   <id: column="" property="">   :

         id:表示查詢結果集中唯一標識。  column:查詢出來的列名。 property:type指定的pojo類中的屬性名。

  <result column="" property=""/>
         reslut:對普通列的標識。    

2.6小結:

  使用ResultType進行結果對映時,只有查詢出來的列名和pojo中的屬性名一致時,才能對映成功。如果列名和pojo的屬性名不一致,則需要通過ResultMap對列名和屬性名進行一個對映。

 3.動態sql:(重點)

    通過mybatis提供的標籤進行動態的sql拼接。

  1.where if

   mybatsi的核心,對sql語句進行靈活的操作,通過表示式進行判斷,對sql進行靈活的拼接、組裝。

   可以對輸出引數進行判斷,若果輸入引數不為空,或是符合條件才進行sql拼接。

	<!-- 使用者資訊的綜合查詢	這是輸入對映傳遞pojo包裝類物件的測試
				UserQueryVo:就是UserCustom的包裝類,在其中也可以包裝其他類的物件
				 UserCustom:是User的擴充套件類-->
		<select id="findUserList" parameterType="UserQueryVo" resultType="UserCustom">
			SELECT * FROM USER 
			<!-- where 子句能夠自動消除第一個and -->
			<where>
				<if test="userCustom != null">
					<if test="userCustom.sex != null and userCustom.sex != '' ">
						and user.sex=#{userCustom.sex} 
					</if>
					<if test="userCustom.username != null and userCustom.username !='' ">
						and user.username LIKE '%${userCustom.username}%'
					</if>
				</if>
			</where> 
		</select>		


    2.sql片段:

     將上面動態sql判斷程式碼塊抽取出來,組成一個sql片段。其他的statement可以對其引用。

<!-- 自定義sql片段,便於複用 -->
	<sql id="sql_mQUery">
				<if test="userCustom != null">
					<if test="userCustom.sex != null and userCustom.sex != '' ">
						and user.sex=#{userCustom.sex} 
					</if>
					<if test="userCustom.username != null and userCustom.username !='' ">
						and user.username LIKE '%${userCustom.username}%'
					</if>
				</if>
		
	</sql>

  引用sql片段:

<!-- 輸出對映的測試,輸出一個簡單型別(查詢資料記錄總數) -->
		<select id="findCount"  parameterType="UserQueryVo" resultType="int">
			SELECT COUNT(*) FROM USER 
			<where>
				<!-- 如果指定的id對應的sql片段不在本mapper.xml中,則需要加入namespace -->
				<include refid="sql_mQUery"></include>
				<!-- 這裡可以再指定sql片段 -->
			</where> 
		</select>



       3.ForEach

   向sql傳遞陣列或者List,Mybatis使用foreach解析:

  例如:

SELECT * FROM USER WHERE id=1 OR id=10 ORid=16

    1.在輸入引數型別中新增List<Integer> :

public class UserQueryVo {

	private UserCustom userCustom;

	private List<Integer> ids;
	

      2.mapper.xml:

<!-- 動態sql之foreach的練習 -->
		
		<select id="findUserByIds" parameterType="UserQueryVo" resultType="UserCustom">
			SELECT * FROM USER
			<where>
				<if test="ids != null">
					<!--使用foreach迴圈遍歷
						 collection:指定集合的輸入物件
						 item:每個遍歷生成的物件
						 open:開始遍歷時生成
						 close:結束遍歷時生成
						separator:遍歷兩個物件中間的拼接
					 -->
					<foreach collection="ids" item="user_id" open="And ( " close=")" separator="OR">
							<!-- 每個遍歷中所需拼接的字串 -->
							id=#{user_id}
					</foreach>
				</if>
			</where>
		</select>