mybatis如何處理返回結(jié)果集
結(jié)果處理
1 簡(jiǎn)單類型輸出映射
返回簡(jiǎn)單基本類型
//查詢管理員總數(shù) int adminCount();
<select id="adminCount" resultType="int">
select count(*) from admin
</select>返回結(jié)果需要定義后才能使用簡(jiǎn)稱
eg:resultType="Admin" 已經(jīng)定義過別名了,所以就可以使用簡(jiǎn)稱
那么java中其它常用類型簡(jiǎn)稱如何使用?(不使用簡(jiǎn)稱就需要用全類名,eg:java.util.List)
在mybatis底層源碼中定義了一些常用的類型的簡(jiǎn)稱



也可以在官網(wǎng)中查看定義好的類型簡(jiǎn)稱或者自己可以重寫已有的類型處理器或創(chuàng)建自己的類型處理器來處理不支持的或非標(biāo)準(zhǔn)的類型,具體參考mybatis – MyBatis 3 | 配置
2 對(duì)象映射
mybatis會(huì)將查詢到的結(jié)果自動(dòng)封裝到一個(gè)對(duì)象中,會(huì)自己創(chuàng)建給定類型的類的對(duì)象(通過是否執(zhí)行無參構(gòu)造方法我們可以看到)
自動(dòng)封裝的條件:
開啟了全局的自動(dòng)結(jié)果映射,PARTIAL默認(rèn)是單張表開啟的

數(shù)據(jù)庫列名與屬性名名字相同,mybatis會(huì)自動(dòng)將查詢結(jié)果封裝到pojo對(duì)象中;
如果不一樣,比如java中使用標(biāo)準(zhǔn)駝峰命名,數(shù)據(jù)庫中使用下劃線連接命名,這個(gè)時(shí)候可以通過開啟駝峰命名自動(dòng)映射或開啟全局設(shè)置實(shí)現(xiàn)自動(dòng)轉(zhuǎn)換

例如:
定義的類中的屬性名:

<select id="findAdminById" parameterType="int" resultType="Admin">
// 定義別名acc、adminGender
select id,account acc,password,admin_gender adminGender from admin where id =#{id};
</select>可以看到列名與屬性名相同的,mybatis會(huì)自動(dòng)將結(jié)果封裝到pojo對(duì)象中,不同的則不會(huì)映射:

開啟駝峰命名自動(dòng)映射后即使不設(shè)置別名,也可以自動(dòng)實(shí)現(xiàn)駝峰映射(eg:admin_gender ---> adminGender)
在全局配置文件中開啟

查詢多行數(shù)據(jù),也就是返回多個(gè)對(duì)象
mybatis會(huì)自動(dòng)創(chuàng)建多個(gè)對(duì)象,并通過set方法為屬性賦值,然后將這些對(duì)象自動(dòng)的封裝到List集合中
List<Admin> findAdmins();
<select id="findAdmins" resultType="Admin">
select id,account,password,admin_gender from admin
</select>
3 特殊處理定義 resultMap
定義 resutlMap
在resutlMap 標(biāo)簽中,我們可以自定義結(jié)果映射
<resultMap id="adminMap" type="Admin">
<id column="id" property="id"></id><!-- 封裝映射主鍵列 -->
<result column="account" property="account"></result>
<result column="password" property="password"></result>
<result column="admin_gender" property="gender"></result>
</resultMap> (1) resutlMap 的 id 屬性是 resutlMap 的唯一標(biāo)識(shí),本例中定義為“adminMap”
(2) resutlMap 的 id 屬性是映射的 POJO 類
(3) id 標(biāo)簽映射主鍵,result 標(biāo)簽映射非主鍵
(4) property 設(shè)置 POJO 的屬性名,column 數(shù)據(jù)庫中列名
使用 resutlMap
<select id="findAdmins" resultMap="adminMap">
select id,account,password,admin_gender from admin
</select>(1) 本例的輸出映射使用的是 resultMap,而非 resultType
(2) resultMap 引用了 adminMap
在說關(guān)聯(lián)查詢之前我們先說一個(gè)問題:
在關(guān)聯(lián)查詢的時(shí)候我們需要同時(shí)獲取幾張表中的數(shù)據(jù),在模型類中進(jìn)行封裝的時(shí)候,我們會(huì)在一個(gè)類中把其他類中已有的屬性再定義一遍,比如以前我們會(huì)在Student類會(huì)中再定義一遍我們需要的Dorm類中已有的屬性,這樣顯然是不合理的,所以我們現(xiàn)在直接在Student中關(guān)聯(lián)Dorm類中的屬性,它就會(huì)將數(shù)據(jù)封裝到關(guān)聯(lián)的類中去,以減少代碼冗余。
eg:

4 多表關(guān)聯(lián)處理結(jié)果集及嵌套查詢
4.1 多表關(guān)聯(lián)處理結(jié)果
resultMap 元素中 association , collection 元素.
- association :是一對(duì)一使用的,用來封裝類中所關(guān)聯(lián)的對(duì)象信息,會(huì)創(chuàng)建一個(gè)關(guān)聯(lián)對(duì)象
- property="類中的屬性名" ,javaType="類型",select表示要執(zhí)行的sql語句
- collection:關(guān)聯(lián)元素處理一對(duì)多關(guān)聯(lián)
4.2 嵌套查詢
將一個(gè)多表關(guān)聯(lián)查詢拆分為多次查詢,查詢主表數(shù)據(jù),然后查詢關(guān)聯(lián)表數(shù)據(jù)
<association property="dorm" column="dormid"
select="findDormById" javaType="Dorm">
</association>(1) select:指定關(guān)聯(lián)查詢對(duì)象的 Mapper Statement ID 為 findDormById
(2) column="dormid" :關(guān)聯(lián)查詢時(shí)將 dormid 列的值傳入 findDormById,傳多個(gè)參數(shù)的話就是{"屬性名"="參數(shù)","屬性名"="參數(shù)"}
(3) collection 和 association 都需要配置 select 和 column 屬性,兩者配置方法相同
案例數(shù)據(jù)庫表:
student表:

dorm表:

admin表:

案例一
在查詢學(xué)生信息的時(shí)候?qū)⑺奚崽?hào)和操作人也查詢出來,這時(shí)就要用到多表關(guān)聯(lián)結(jié)果處理
方法一:通過三張表關(guān)聯(lián)查詢,一次把信息都查詢出來,在封裝信息的時(shí)候再處理
Student findStudentById(int id);
<resultMap id="studentMap" type="com.ffyc.mybatispro.model.Student">
<!--
mybatis默認(rèn)配置,一旦出現(xiàn)了嵌套關(guān)聯(lián)查詢,就把自動(dòng)映射關(guān)閉了,所以這里我們需要自定義結(jié)果映射
要想讓它繼續(xù)自動(dòng)映射,就需要在全局配置文件中設(shè)置autoMappingBehavior屬性值為true,
我們是不建議在多表查詢時(shí)開啟的,因?yàn)檫@需要高度規(guī)范的命名
-->
<id column="id" property="id"></id>
<result column="num" property="num"></result>
<result column="name" property="name"></result>
<result column="gender" property="gender"></result>
<result column="birthday" property="birthday"></result>
<result column="oper_time" property="operTime"></result>
<!--
association:用來封裝關(guān)聯(lián)的對(duì)象信息
property="dorm", 就是創(chuàng)建一個(gè)關(guān)聯(lián)的對(duì)象
-->
<association property="dorm" javaType="Dorm">
<!--
這里的column是數(shù)據(jù)庫中的列名或者我們定義的列的別名
property是Dorm類中的屬性
-->
<result column="dormNum" property="num"></result>
</association>
<association property="admin" javaType="Admin">
<result column="account" property="account"></result>
</association>
</resultMap><select id="findStudentById" parameterType="int" resultMap="studentMap">
SELECT
s.id,
s.num,
s.name,
s.gender,
s.birthday,
d.num dormNum,
a.account,
s.oper_time
FROM student s
LEFT JOIN dorm d ON s.dormid = d.id
LEFT JOIN admin a ON s.adminid = a.id
WHERE s.id = #{id}
</select>測(cè)試:
@Test
public void find() {
SqlSession sqlSession = MybatisUtil.getSqlSession();
StudentDao studentDao = sqlSession.getMapper(StudentDao.class);
Student student = studentDao.findStudentById(1);
sqlSession.commit();
sqlSession.close();
}
在這里還要補(bǔ)充一點(diǎn):如果在拿到學(xué)生信息后,需要獲取學(xué)生的宿舍號(hào),首先要拿到學(xué)生對(duì)象中的Dorm對(duì)象,然后再獲取Dorm對(duì)象中屬性
System.out.println(student.getDorm().getNum());
前端也一樣

注意:查詢多個(gè)學(xué)生信息只需要將sq語句中的WHERE s.id = #{id}這個(gè)條件給去掉,resultMap和查詢一個(gè)是一樣的
List<Student> findStudents();
方法二:嵌套查詢(把sql分成多次查詢,先查詢學(xué)生信息,再通過外鍵查詢宿舍和操作人信息)
<resultMap id="studentMap" type="Student">
<id column="id" property="id"></id>
<result column="num" property="num"></result>
<result column="name" property="name"></result>
<result column="gender" property="gender"></result>
<result column="birthday" property="birthday"></result>
<result column="oper_time" property="operTime"></result>
<!--
select="findDormById" 查詢語句id
column="dormid" 將查詢到的dormid作為條件再查詢
javaType="Dorm" 類型
-->
<association property="dorm" column="dormid"
select="findDormById" javaType="Dorm"></association>
<association property="admin" column="adminid"
select="findAdminById" javaType="Admin"></association>
</resultMap><select id="findStudentById" resultType="Student" resultMap="studentMap">
select id,num,name,gender,birthday,dormid,adminid from student where id = #{id}
</select><select id="findDormById" resultType="Dorm">
select num from dorm where id = #{dormid}
</select><select id="findAdminById" resultType="Admin">
select account from admin where id = #{adminid}
</select>測(cè)試:

案例二
在查詢宿舍的同時(shí)查詢出這個(gè)宿舍中所住學(xué)生的信息
方法1:關(guān)聯(lián)查詢
類中屬性定義:

Dorm findDormById(int id);
<resultMap id="dormMap" type="Dorm">
<id column="id" property="id"></id>
<result column="num" property="num"></result>
<association property="admin" javaType="Admin">
<result column="account" property="account"></result>
</association>
<!--
property="students" 屬性
javaType="list" students的類型(list為類型簡(jiǎn)稱)
ofType="Student" 集合里所裝數(shù)據(jù)的類型
-->
<collection property="students" javaType="list" ofType="Student">
<result column="snum" property="num"></result>
<result column="name" property="name"></result>
</collection>
</resultMap><select id="findDormById" resultMap="dormMap" resultType="Dorm">
SELECT
d.id,
d.num,
s.num,
s.name,
a.account
FROM dorm d
LEFT JOIN admin a ON d.adminid = a.id
LEFT JOIN student s ON d.id = s.dormid
WHERE d.id = 1
</select>
方法2:嵌套查詢
<resultMap id="dormMap2" type="Dorm">
<id column="id" property="id"></id>
<result column="num" property="num"></result>
<association property="admin" column="adminid" javaType="Admin" select="findAdminById1"></association>
<collection property="students" javaType="list" ofType="Student" column="id"
select="findStudents1"></collection>
</resultMap><select id="findDormById1" resultMap="dormMap2" resultType="Dorm">
SELECT id,num,adminid FROM dorm WHERE id = #{id}
</select>
<select id="findAdminById1" resultType="Admin">
SELECT account FROM admin WHERE id = #{adminid}
</select>
<select id="findStudents1" resultType="Student">
SELECT num,NAME FROM student WHERE dormid = #{id}
</select>測(cè)試:

查詢所有的宿舍及關(guān)聯(lián)的學(xué)生信息
方法1:關(guān)聯(lián)查詢
List<Dorm> findDorms();
<select id="findDorms" resultMap="dormMap">
SELECT
d.id,
d.num,
s.num,
s.name,
a.account
FROM dorm d
LEFT JOIN admin a ON d.adminid = a.id
LEFT JOIN student s ON d.id = s.dormid
</select>測(cè)試:
@Test
public void find(){
SqlSession sqlSession = MybatisUtil.getSqlSession();
DormDao dormDao = sqlSession.getMapper(DormDao.class);
//查詢每個(gè)宿舍,并關(guān)聯(lián)每個(gè)宿舍中有多少個(gè)學(xué)生
List<Dorm> dorms = dormDao.findDorms();
/*
對(duì)查詢結(jié)果進(jìn)行獲取輸出
*/
// 遍歷所有宿舍
for (Dorm dorm:dorms){
System.out.println(dorm);
// 獲取到宿舍中所有學(xué)生信息
for (Student student:dorm.getStudents()){
System.out.println(student.getNum()+":"+student.getName());
}
}
sqlSession.close();
}可以看到查詢出了所有的宿舍以及宿舍所住學(xué)生的信息:

方法2:嵌套查詢
<resultMap id="dormMap" type="Dorm">
<id column="id" property="id"></id>
<result column="num" property="num"></result>
<association property="admin" column="adminid" javaType="Admin" select="findAdminById"></association>
<collection property="students" javaType="list" ofType="Student" column="id"
select="findStudents"></collection>
</resultMap><select id="findDorms" resultType="Dorm" resultMap="dormMap">
SELECT id,num,adminid FROM dorm
</select>
<select id="findAdminById" resultType="Admin">
SELECT account FROM admin WHERE id = #{adminid}
</select>
<select id="findStudents" resultType="Student">
SELECT num,NAME FROM student WHERE dormid = #{id}
</select>測(cè)試:

總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
聊聊Kotlin?中?lateinit?和?lazy?的原理區(qū)別
使用 Kotlin 進(jìn)行開發(fā),對(duì)于 latelinit 和 lazy 肯定不陌生。但其原理上的區(qū)別,可能鮮少了解過,借著本篇文章普及下這方面的知識(shí),感興趣的朋友一起看看吧2022-07-07
解決kafka:org.apache.kafka.common.errors.TimeoutException問題
這篇文章主要介紹了解決kafka:org.apache.kafka.common.errors.TimeoutException問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
SpringBoot文件訪問映射如何實(shí)現(xiàn)
這篇文章主要介紹了SpringBoot文件訪問映射如何實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02
Java基礎(chǔ)之多線程方法狀態(tài)和創(chuàng)建方法
Java中可以通過Thread類和Runnable接口來創(chuàng)建多個(gè)線程,下面這篇文章主要給大家介紹了關(guān)于Java基礎(chǔ)之多線程方法狀態(tài)和創(chuàng)建方法的相關(guān)資料,需要的朋友可以參考下2021-09-09
mybatisPlus填坑之邏輯刪除的實(shí)現(xiàn)
本文主要介紹了mybatisPlus填坑之邏輯刪除的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01
java基礎(chǔ)--自己動(dòng)手實(shí)現(xiàn)一個(gè)LRU
這篇文章主要介紹了運(yùn)用方案如何實(shí)現(xiàn)LUR,文章中通過代碼講解的非常詳細(xì),對(duì)大家的工作或?qū)W習(xí)有一定的參考價(jià)值,感興趣的朋友可以參考一下2021-08-08
深度解析Java @Serial 注解及常見錯(cuò)誤案例
Java14引入@Serial注解,用于編譯時(shí)校驗(yàn)序列化成員,替代傳統(tǒng)方式解決運(yùn)行時(shí)錯(cuò)誤,適用于Serializable類的方法/字段,需注意簽名和位置校驗(yàn),建議新項(xiàng)目采用,本文給大家介紹Java @Serial 注解的相關(guān)知識(shí),感興趣的朋友一起看看吧2025-07-07
Java中雙冒號(hào)(::)運(yùn)算操作符用法詳解
這篇文章主要給大家介紹了關(guān)于Java中雙冒號(hào)(::)運(yùn)算操作符用法的相關(guān)資料,雙冒號(hào)運(yùn)算操作符是類方法的句柄,lambda表達(dá)式的一種簡(jiǎn)寫,這種簡(jiǎn)寫的學(xué)名叫eta-conversion或者叫η-conversion,需要的朋友可以參考下2023-11-11

