【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>