mybatis如何處理返回結(jié)果集
結(jié)果處理
1 簡單類型輸出映射
返回簡單基本類型
//查詢管理員總數(shù) int adminCount();
<select id="adminCount" resultType="int"> select count(*) from admin </select>
返回結(jié)果需要定義后才能使用簡稱
eg:resultType="Admin" 已經(jīng)定義過別名了,所以就可以使用簡稱
那么java中其它常用類型簡稱如何使用?(不使用簡稱就需要用全類名,eg:java.util.List)
在mybatis底層源碼中定義了一些常用的類型的簡稱
也可以在官網(wǎng)中查看定義好的類型簡稱或者自己可以重寫已有的類型處理器或創(chuàng)建自己的類型處理器來處理不支持的或非標(biāo)準(zhǔn)的類型,具體參考mybatis – MyBatis 3 | 配置
2 對象映射
mybatis會將查詢到的結(jié)果自動封裝到一個對象中,會自己創(chuàng)建給定類型的類的對象(通過是否執(zhí)行無參構(gòu)造方法我們可以看到)
自動封裝的條件:
開啟了全局的自動結(jié)果映射,PARTIAL默認是單張表開啟的
數(shù)據(jù)庫列名與屬性名名字相同,mybatis會自動將查詢結(jié)果封裝到pojo對象中;
如果不一樣,比如java中使用標(biāo)準(zhǔn)駝峰命名,數(shù)據(jù)庫中使用下劃線連接命名,這個時候可以通過開啟駝峰命名自動映射或開啟全局設(shè)置實現(xiàn)自動轉(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會自動將結(jié)果封裝到pojo對象中,不同的則不會映射:
開啟駝峰命名自動映射后即使不設(shè)置別名,也可以自動實現(xiàn)駝峰映射(eg:admin_gender ---> adminGender)
在全局配置文件中開啟
查詢多行數(shù)據(jù),也就是返回多個對象
mybatis會自動創(chuàng)建多個對象,并通過set方法為屬性賦值,然后將這些對象自動的封裝到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)識,本例中定義為“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)查詢之前我們先說一個問題:
在關(guān)聯(lián)查詢的時候我們需要同時獲取幾張表中的數(shù)據(jù),在模型類中進行封裝的時候,我們會在一個類中把其他類中已有的屬性再定義一遍,比如以前我們會在Student類會中再定義一遍我們需要的Dorm類中已有的屬性,這樣顯然是不合理的,所以我們現(xiàn)在直接在Student中關(guān)聯(lián)Dorm類中的屬性,它就會將數(shù)據(jù)封裝到關(guān)聯(lián)的類中去,以減少代碼冗余。
eg:
4 多表關(guān)聯(lián)處理結(jié)果集及嵌套查詢
4.1 多表關(guān)聯(lián)處理結(jié)果
resultMap 元素中 association , collection 元素.
- association :是一對一使用的,用來封裝類中所關(guān)聯(lián)的對象信息,會創(chuàng)建一個關(guān)聯(lián)對象
- property="類中的屬性名" ,javaType="類型",select表示要執(zhí)行的sql語句
- collection:關(guān)聯(lián)元素處理一對多關(guān)聯(lián)
4.2 嵌套查詢
將一個多表關(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)查詢對象的 Mapper Statement ID 為 findDormById
(2) column="dormid" :關(guān)聯(lián)查詢時將 dormid 列的值傳入 findDormById,傳多個參數(shù)的話就是{"屬性名"="參數(shù)","屬性名"="參數(shù)"}
(3) collection 和 association 都需要配置 select 和 column 屬性,兩者配置方法相同
案例數(shù)據(jù)庫表:
student表:
dorm表:
admin表:
案例一
在查詢學(xué)生信息的時候?qū)⑺奚崽柡筒僮魅艘膊樵兂鰜恚@時就要用到多表關(guān)聯(lián)結(jié)果處理
方法一:通過三張表關(guān)聯(lián)查詢,一次把信息都查詢出來,在封裝信息的時候再處理
Student findStudentById(int id);
<resultMap id="studentMap" type="com.ffyc.mybatispro.model.Student"> <!-- mybatis默認配置,一旦出現(xiàn)了嵌套關(guān)聯(lián)查詢,就把自動映射關(guān)閉了,所以這里我們需要自定義結(jié)果映射 要想讓它繼續(xù)自動映射,就需要在全局配置文件中設(shè)置autoMappingBehavior屬性值為true, 我們是不建議在多表查詢時開啟的,因為這需要高度規(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)的對象信息 property="dorm", 就是創(chuàng)建一個關(guān)聯(lián)的對象 --> <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>
測試:
@Test public void find() { SqlSession sqlSession = MybatisUtil.getSqlSession(); StudentDao studentDao = sqlSession.getMapper(StudentDao.class); Student student = studentDao.findStudentById(1); sqlSession.commit(); sqlSession.close(); }
在這里還要補充一點:如果在拿到學(xué)生信息后,需要獲取學(xué)生的宿舍號,首先要拿到學(xué)生對象中的Dorm對象,然后再獲取Dorm對象中屬性
System.out.println(student.getDorm().getNum());
前端也一樣
注意:查詢多個學(xué)生信息只需要將sq語句中的WHERE s.id = #{id}這個條件給去掉,resultMap和查詢一個是一樣的
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>
測試:
案例二
在查詢宿舍的同時查詢出這個宿舍中所住學(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為類型簡稱) 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>
測試:
查詢所有的宿舍及關(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>
測試:
@Test public void find(){ SqlSession sqlSession = MybatisUtil.getSqlSession(); DormDao dormDao = sqlSession.getMapper(DormDao.class); //查詢每個宿舍,并關(guān)聯(lián)每個宿舍中有多少個學(xué)生 List<Dorm> dorms = dormDao.findDorms(); /* 對查詢結(jié)果進行獲取輸出 */ // 遍歷所有宿舍 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>
測試:
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Spring AOP常見使用場景、術(shù)語及設(shè)計模式應(yīng)用方式
AOP是一種編程思想,可以將橫切關(guān)注點從業(yè)務(wù)邏輯中分離出來,以便更好地管理和維護,它通過使用Aspect、JoinPoint、Advice等術(shù)語來實現(xiàn),代理、裝飾器和攔截器等設(shè)計模式在AOP中經(jīng)常被使用2024-12-12GateWay路由規(guī)則與動態(tài)路由詳細介紹
這篇文章主要介紹了GateWay路由規(guī)則與GateWay動態(tài)路由,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09SpringMVC實現(xiàn)Validation校驗過程詳解
這篇文章主要介紹了SpringMVC實現(xiàn)Validation校驗過程詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-11-11Springboot下RedisTemplate的兩種序列化方式實例詳解
這篇文章主要介紹了Springboot下RedisTemplate的兩種序列化方式,通過定義一個配置類,自定義RedisTemplate的序列化方式,結(jié)合實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-09-09使用Java7的Files工具類和Path接口來訪問文件的方法
下面小編就為大家分享一篇使用Java7的Files工具類和Path接口來訪問文件的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2017-11-11