Mybatis分解式查詢(xún)使用方法
一、Mybatis一對(duì)多分解式查詢(xún)
分解式查詢(xún)就是將一條Sql語(yǔ)句拆分成多條
在MyBatis多表查詢(xún)中,使用連接查詢(xún)時(shí)一個(gè)Sql語(yǔ)句就可以查詢(xún)出所有的數(shù)據(jù)。如:
# 查詢(xún)班級(jí)時(shí)關(guān)聯(lián)查詢(xún)出學(xué)生
select *
from classes
left join student
on student.classId = classes.cid
也可以使用分解式查詢(xún),即將一個(gè)連接Sql語(yǔ)句分解為多條Sql語(yǔ)句,如:
# 查詢(xún)班級(jí)時(shí)關(guān)聯(lián)查詢(xún)出學(xué)生
select * from classes;
select * from student where classId = 1;
select * from student where classId = 2;
這種寫(xiě)法也叫N+1查詢(xún)。
連接查詢(xún):
優(yōu)點(diǎn):降低查詢(xún)次數(shù),從而提高查詢(xún)效率。
缺點(diǎn):如果查詢(xún)返回的結(jié)果集較多會(huì)消耗內(nèi)存空間。
N+1查詢(xún):
優(yōu)點(diǎn):結(jié)果集分步獲取,節(jié)省內(nèi)存空間。
缺點(diǎn):由于需要執(zhí)行多次查詢(xún),相比連接查詢(xún)效率低。
我們以查詢(xún)班級(jí)時(shí)關(guān)聯(lián)查詢(xún)出學(xué)生為例,使用N+1查詢(xún):
1. 新增持久層接口方法
新增ClassesMapper2.java接口
package com.example.mapper; import com.example.pojo.Classes; import java.util.List; public interface ClassesMapper2 { List<Classes> findAll(); }
新增StudentMapper.java接口
package com.example.mapper; import com.example.pojo.Student; import java.util.List; public interface StudentMapper2 { List<Student> findByClassId(int classId); }
2. 新增映射文件對(duì)應(yīng)的標(biāo)簽
新增ClassesMapper.xml映射文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.mapper.ClassesMapper2"> <!-- 自定義映射關(guān)系 --> <resultMap id="myClassesMapper" type="com.example.pojo.Classes"> <id property="cid" column="cid"/> <result property="className" column="className"/> <!-- select: 從表查詢(xún)調(diào)用的方法 column:調(diào)用方法時(shí)傳入的參數(shù)字段 --> <collection property="studentList" column="cid" ofType="com.example.pojo.Student" select="com.example.mapper.StudentMapper2.findByClassId"/> </resultMap> <select id="findAll" resultMap="myClassesMapper"> select * from classes </select> </mapper>
新增StudentMapper.xml映射文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.mapper.StudentMapper2"> <select id="findByClassId" parameterType="int" resultType="com.example.pojo.Student"> select * from student where classId = ${classId} </select> </mapper>
3. 新增測(cè)試方法
// 分解式查詢(xún)一對(duì)多 @Test public void testFindAllClasses2(){ ClassesMapper2 classesMapper2 = session.getMapper(ClassesMapper2.class); List<Classes> all = classesMapper2.findAll(); all.forEach(System.out::println); }
4. 運(yùn)行效果
在這里我們可以看到確實(shí)是分開(kāi)了了兩條查詢(xún)語(yǔ)句
二、Mybatis一對(duì)一分解式查詢(xún)
查詢(xún)學(xué)生時(shí)關(guān)聯(lián)查詢(xún)出班級(jí)也可以使用分解式查詢(xún),首先將查詢(xún)語(yǔ)句分開(kāi):
select * from student;
select * from classes where cid = ?
1. 新增持久層接口方法
新增StudentMapper3.java接口
package com.example.mapper; import com.example.pojo.Student; import java.util.List; public interface StudentMapper3 { // 查詢(xún)所有學(xué)生 List<Student> findAll(); }
新增ClassesMapper3.java接口
package com.example.mapper; import com.example.pojo.Classes; import java.util.List; public interface ClassesMapper3 { // 根據(jù)ID查詢(xún)班級(jí) Classes findById(int cid); }
2. 新增映射文件對(duì)應(yīng)的標(biāo)簽
新增ClassesMapper.xml映射文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.mapper.ClassesMapper3"> <select id="findByCid" resultType="com.example.pojo.Classes" parameterType="int"> select * from classes where cid = ${cid} </select> </mapper>
新增StudentMapper.xml映射文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.mapper.StudentMapper3"> <!-- 自定義映射關(guān)系 --> <resultMap id="MyClassesMapper" type="com.example.pojo.Student"> <id property="sid" column="sid"/> <result property="name" column="name"/> <result property="age" column="age"/> <result property="sex" column="sex"/> <!-- select: 從表查詢(xún)調(diào)用的方法 column:調(diào)用方法時(shí)傳入的參數(shù)字段 --> <association property="classes" column="classId" javaType="com.example.pojo.Classes" select="com.example.mapper.ClassesMapper3.findByCid"/> </resultMap> <select id="findAll" resultMap="MyClassesMapper"> select * from student </select> </mapper>
3. 新增測(cè)試方法
// 分解式查詢(xún)一對(duì)一 @Test public void testFindAllStudent2(){ StudentMapper3 studentMapper3 = session.getMapper(StudentMapper3.class); List<Student> all = studentMapper3.findAll(); all.forEach(System.out::println); }
4. 運(yùn)行效果
OK,確實(shí)是查詢(xún)出來(lái)了。
三、Mybatis延遲加載
分解式查詢(xún)又分為兩種加載方式:
立即加載:在查詢(xún)主表時(shí)就執(zhí)行所有的Sql語(yǔ)句。
延遲加載:又叫懶加載,首先執(zhí)行主表的查詢(xún)語(yǔ)句,使用從表數(shù)據(jù)時(shí)才觸發(fā)從表的查詢(xún)語(yǔ)句。
延遲加載在獲取關(guān)聯(lián)數(shù)據(jù)時(shí)速度較慢,但可以節(jié)約資源,即用即取。
1. 開(kāi)啟延遲加載
設(shè)置所有的N+1查詢(xún)都為延遲加載,在Mybatis配置文件中添加以下設(shè)置:
<settings> <setting name="lazyLoadingEnabled" value="true"/> <setting name="lazyLoadTriggerMethods" value=""/> </settings>
設(shè)置某個(gè)方法為延遲加載:
在 <association> 、 <collection> 中添加fetchType屬性設(shè)置加載方式。
lazy:延遲加載;eager:立即加載。
2. 測(cè)試延遲加載
由于打印對(duì)象時(shí)會(huì)調(diào)用對(duì)象的 toString 方法, toString 方法默認(rèn)會(huì)觸發(fā)延遲加載的查詢(xún),所以我們無(wú)法測(cè)試出延遲加載的效果。
我們?cè)谂渲梦募O(shè)置lazyLoadTriggerMethods屬性,該屬性指定對(duì)象的什么方法觸發(fā)延遲加載,設(shè)置為空字符串即可。
測(cè)試方法:
@Test public void testFindAllClasses2(){ ClassesMapper2 classesMapper2 = session.getMapper(ClassesMapper2.class); List<Classes> all = classesMapper2.findAll(); all.forEach(System.out::println); System.out.println("---------------------"); System.out.println(all.get(0).getStudentList()); }
運(yùn)行結(jié)果:
OK,這個(gè)很明顯了,就是第一次查詢(xún)的時(shí)候沒(méi)有將學(xué)生列表查詢(xún)出來(lái),等到后續(xù)需要查詢(xún)的時(shí)候載查詢(xún)。
一般情況下,一對(duì)多查詢(xún)使用延遲加載,一對(duì)一查詢(xún)使用立即加載。
到此這篇關(guān)于Mybatis分解式查詢(xún)使用方法的文章就介紹到這了,更多相關(guān)Mybatis分解式查詢(xún)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MyBatis動(dòng)態(tài)SQL實(shí)現(xiàn)配置過(guò)程解析
這篇文章主要介紹了MyBatis動(dòng)態(tài)SQL實(shí)現(xiàn)配置過(guò)程解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03詳解Java項(xiàng)目中讀取properties文件
本篇文章主要介紹了Java項(xiàng)目中讀取properties文件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2016-12-12logback FixedWindowRollingPolicy固定窗口算法重命名文件滾動(dòng)策略
這篇文章主要介紹了FixedWindowRollingPolicy根據(jù)logback 固定窗口算法重命名文件滾動(dòng)策略源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11詳解大數(shù)據(jù)處理引擎Flink內(nèi)存管理
Flink是jvm之上的大數(shù)據(jù)處理引擎,jvm存在java對(duì)象存儲(chǔ)密度低、full gc時(shí)消耗性能,gc存在stw的問(wèn)題,同時(shí)omm時(shí)會(huì)影響穩(wěn)定性。針對(duì)頻繁序列化和反序列化問(wèn)題flink使用堆內(nèi)堆外內(nèi)存可以直接在一些場(chǎng)景下操作二進(jìn)制數(shù)據(jù),減少序列化反序列化消耗。本文帶你詳細(xì)理解其原理。2021-05-05在Java中FreeMarker?模板來(lái)定義字符串模板
這篇文章主要介紹了在Java中FreeMarker?模板來(lái)定義字符串模板,文章基于Java的相關(guān)資料展開(kāi)詳細(xì)內(nèi)容,需要的小伙伴可以參考一下2022-04-04詳解SpringSecurity如何實(shí)現(xiàn)前后端分離
這篇文章主要為大家介紹了詳解SpringSecurity如何實(shí)現(xiàn)前后端分離,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03