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)文章
Spring AOP常見使用場(chǎng)景、術(shù)語及設(shè)計(jì)模式應(yīng)用方式
AOP是一種編程思想,可以將橫切關(guān)注點(diǎn)從業(yè)務(wù)邏輯中分離出來,以便更好地管理和維護(hù),它通過使用Aspect、JoinPoint、Advice等術(shù)語來實(shí)現(xiàn),代理、裝飾器和攔截器等設(shè)計(jì)模式在AOP中經(jīng)常被使用2024-12-12GateWay路由規(guī)則與動(dòng)態(tài)路由詳細(xì)介紹
這篇文章主要介紹了GateWay路由規(guī)則與GateWay動(dòng)態(tài)路由,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09SpringMVC實(shí)現(xiàn)Validation校驗(yàn)過程詳解
這篇文章主要介紹了SpringMVC實(shí)現(xiàn)Validation校驗(yàn)過程詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-11-11Java實(shí)現(xiàn)冒泡排序簡(jiǎn)單示例
冒泡排序(Bubble Sort)是一種簡(jiǎn)單的排序算法,它重復(fù)地走訪過要排序的數(shù)列,一次比較兩個(gè)元素,如果他們的順序錯(cuò)誤就把他們交換過來,下面這篇文章主要給大家介紹了關(guān)于Java實(shí)現(xiàn)冒泡排序的相關(guān)資料,需要的朋友可以參考下2023-06-06Springboot下RedisTemplate的兩種序列化方式實(shí)例詳解
這篇文章主要介紹了Springboot下RedisTemplate的兩種序列化方式,通過定義一個(gè)配置類,自定義RedisTemplate的序列化方式,結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-09-09使用Java7的Files工具類和Path接口來訪問文件的方法
下面小編就為大家分享一篇使用Java7的Files工具類和Path接口來訪問文件的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2017-11-11