MyBatis中Mapper對映檔案的輸入(parameterType)和輸出(resultType)對映
Mapper.xml對映檔案中定義了操作資料庫的sql,每個sql是一個statement,對映檔案是mybatis的核心。
輸入型別parameterType
1)傳遞簡單型別
傳遞簡單型別,前兩節課都見過,這裡只給出案例:
2)傳遞pojo物件
MyBatis使用ognl表示式解析物件欄位的值,#{}或者${}括號中的值為pojo的屬性名稱。傳遞pojo物件之前也已講過,這裡同樣只給出案例:
3)傳遞pojo包裝物件
開發中通過pojo傳遞查詢條件,查詢條件是綜合的查詢條件,不僅包括使用者查詢條件還包括其它的查詢條件,這時可以使用包裝物件傳遞輸入引數。即一個pojo類的屬性是另一個pojo類物件。
例如,新建vo如下:
public class QueryVo {
private String query;
private User user;
public String getQuery() {
return query;
}
public void setQuery(String query) {
this.query = query;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
在UserMapper介面中定義方法:
/**
* 根據QueryVo提供的資料進行查詢
* @param vo
* @return
*/
User getUserByQueryVo(QueryVo vo);
接下來我們就要在UserMapper.xml對映檔案中編寫sql語句了,即在UserMapper.xml對映檔案中新增如下配置資訊:
<select id="getUserByQueryVo" parameterType="com.oak.po.QueryVo">
select * from `user` where id=#{user.id} and name=#{user.name}
</ select>
輸出型別(resultType)
1)輸出簡單型別
例如:檢視user表中的記錄總數,首先在UserMapper介面中定義方法:
/**
* 得到總記錄數
* @return
*/
Integer count();
在UserMapper.xml中配置:
<!-- 查詢user表中的記錄總數 -->
<select id="count" resultType="int">
select count(id) from `user`
</select>
輸出簡單型別必須查詢出來的結果集只有一條記錄,最終將第一個欄位的值轉換為輸出型別。
2)輸出POJO物件
輸出pojo列表,我之前同樣已講過,這裡只給出案例:
3)輸出POJO列表(返回值為集合)
輸出pojo列表,我之前同樣已講過,這裡只給出案例:
我們只要返回值型別定義為返回集合中一個元素的型別即可(集合的泛型)。
注意:
如果查詢的欄位名與返回值屬性名不一致則無法完成對映!所以要保證select欄位名與返回值型別屬性一致!也就是返回的結果的列名和pojo中的屬性要一致才可以自動對映
案例
我們重新定義一個型別為角色role,每一個角色對應一個使用者,首先在資料庫中建立role表
CREATE TABLE `NewTable` (
`role_id` int(4) NOT NULL AUTO_INCREMENT ,
`role_name` varchar(7) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
`user_id` int(4) NOT NULL ,
PRIMARY KEY (`role_id`)
)ENGINE=InnoDB
DEFAULT CHARACTER SET=utf8 COLLATE=utf8_general_ci;
在po包中新建Role:
public class Role {
private Integer roleId;
private String roleName;
private Integer userId;
//方法略
}
在UserMapper介面中定義方法:
/**
* 根據user_id查詢role資訊
* @param userId
* @return
*/
Role findRoleByUserId(int userId);
在UserMapper.xml中定義sql對映:
<!-- 根據user 的 id查詢role資訊 -->
<select id="findRoleByUserId" parameterType="int"
resultType="com.oak.po.Role">
select * from `role` where user_id=#{id}
</select>
注意:此處查詢的是select * 也就是查詢的是role表中的欄位名role_id,role_name和user_id
測試:
@Test
public void testFindRoleByUserId(){
//第四步 得到sqlSession,與Spring整合後省略
SqlSession sqlSession=sqlSessionFactory.openSession();
//獲得代理物件(與Spring整合後只需要通過Spring容器拿到UserMapper介面的代理物件就行了)
UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
Role role=userMapper.findRoleByUserId(2);
System.out.println(role);
sqlSession.close();
}
檢視結果:
你會發現查詢有一條結果,但是封裝到返回物件中時失敗了。
所有這裡一定要注意:返回的結果的列名和pojo中的屬性要一致才可以自動對映。
這裡我們可以使用別名的方式,把xml中的sql修改為:
<!-- 根據user 的 id查詢role資訊 -->
<select id="findRoleByUserId" parameterType="int"
resultType="com.oak.po.Role">
select role_id roleId,role_name roleName,user_id userId from `role` where user_id=#{id}
</select>
測試:
這種方式比較簡單粗暴,其實要達到我們所預期的效果,還有另一種方式,那就是使用resultMap這個屬性
resultMap
resultType可以指定pojo將查詢結果對映為pojo,但需要pojo的屬性名和sql查詢的列名一致方可對映成功。如果sql查詢欄位名和pojo的屬性名不一致,可以通過resultMap將欄位名和屬性名作一個對應關係 ,resultMap實質上還需要將查詢結果對映到pojo物件中。
resultMap可以實現將查詢結果對映為複雜型別的pojo,比如在查詢結果對映物件中包括pojo和list實現一對一查詢和一對多查詢。
我們修改對映檔案中的sql,不使用取別名的方式,把resultType替換為resultMap:
<!-- 根據user 的 id查詢role資訊 -->
<select id="findRoleByUserId" parameterType="int" resultMap="role_list_map">
select role_id,role_name,user_id from `role` where user_id=#{id}
</select>
然後定義resultMap,由於對映檔案中sql查詢列和Role屬性不一致,因此需要定義resultMap:role_list_map將sql查詢列和Role類屬性對應起來:
<resultMap type="com.oak.po.Role" id="role_list_map">
<!-- id是主鍵的對映,其中property是pojo中主鍵的屬性,column是返回結果中主鍵的列 -->
<id property="roleId" column="role_id" />
<!-- 普通列使用result對映 -->
<result property="roleName" column="role_name" />
<result property="userId" column="user_id" />
</resultMap>
-
type:指resultMap要對映成的資料型別(返回結果對映的pojo,可以使用別名)。
-
< id />:此屬性表示查詢結果集的唯一標識,非常重要。如果是多個欄位為複合唯一約束則定義多個< id />(複合主鍵時多個)。
-
< result />:普通列使用result標籤對映。
-
property:表示POJO類的屬性。
-
column:表示sql查詢出來的欄位名(列名)。
-
column和property放在一塊兒表示將sql查詢出來的欄位對映到指定的pojo類屬性上。
可以直接測試