Mybatis-Plus或PageHelper多表分頁查詢總條數(shù)不對問題的解決方法
前言
項目老大說項目需要重構(gòu)搜索功能,決定交給我這個比較閑的人! 嗯 ???
因為以前的項目數(shù)據(jù)不大,都不能說不大,是很少,所有搜索采用的是MySQL中的like模糊搜索操作的,他希望我改一下;
我第一時間想到了ES,但他說沒必要用ES,等以后數(shù)據(jù)量大了再換,現(xiàn)在只是稍微多了一些數(shù)據(jù),沒必要
Ok!那我就用了MySQL自帶的全文檢索功能,因為本文主要說的還是Mybatis-Plus的問題,所以全文檢索在下面只會提到怎么使用,以及一些問題
好像說了一大堆廢話,回歸正題!
項目以前分頁搜索用的是PageHelper這個插件,但公司封裝的3.0框架中已經(jīng)封裝了Mybatis-Plus,所以我采用了Mybatis-Plus的分頁插件
一、問題說明
場景:
老師表是有4條數(shù)據(jù),每個老師對應(yīng)2個學(xué)生
使用的是兩個表聯(lián)查letf join加Mybatis的級聯(lián)查詢,一次性獲取所有數(shù)據(jù)出現(xiàn)3個問題:
1、數(shù)據(jù)總條數(shù)以及頁數(shù)不對
2、數(shù)據(jù)分頁數(shù)量不對
3、數(shù)據(jù)混亂
已下是我有問題的代碼:
1、引入依賴
版本選擇盡量3.4+
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.1</version>
</dependency>
2、Mybatis-Plus配置
@Configuration
public class MybatisPlusConfig {
/**
* 插件注冊
*
* @param paginationInnerInterceptor 分頁插件
* @return MybatisPlus攔截器
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(PaginationInnerInterceptor paginationInnerInterceptor) {
MybatisPlusInterceptor mp = new MybatisPlusInterceptor();
mp.addInnerInterceptor(paginationInnerInterceptor);
return mp;
}
//分頁插件
@Bean
public PaginationInnerInterceptor paginationInnerInterceptor() {
PaginationInnerInterceptor pii = new PaginationInnerInterceptor();
pii.setMaxLimit(20L);
pii.setDbType(DbType.MYSQL);
//當超過最大頁數(shù)時不會報錯
pii.setOverflow(true);
return pii;
}
}
3、創(chuàng)建mapper層
創(chuàng)建了一個返回實體類
TeacherVO,包括老師信息以及學(xué)生信息,以及一個傳入的參數(shù)類TeacherRequestVo
@Data
public class TeacherVO {
/**
* 跟學(xué)生表關(guān)聯(lián)的字段
*/
private String classs;
private String tname;
private String tsex;
private Date tbirthday;
private String prof;
private String depart;
private List<Student> student;
}
@Data
public class TeacherRequestVo {
private String classs;
private String tname;
private String sname;
}
public interface TeacherMapper extends BaseMapper<Teacher> {
/**
* 獲取老師所帶班級中的所有老師及學(xué)生信息
* @param page mybatisplus自帶的page類
* @param teacherRequestVo 傳入的參數(shù)
* @return
*/
Page<TeacherVO> getAll(Page<TeacherVO> page, TeacherRequestVo teacherRequestVo);
}
4、編寫xxxMapper.xml文件
<resultMap id="GetAllMap" type="com.qjj.demo.entity.vo.TeacherVO">
<!--@mbg.generated-->
<!--@Table teacher-->
<result column="classs" jdbcType="VARCHAR" property="classs"/>
<result column="Tname" jdbcType="VARCHAR" property="tname"/>
<result column="Tsex" jdbcType="VARCHAR" property="tsex"/>
<result column="Tbirthday" jdbcType="TIMESTAMP" property="tbirthday"/>
<result column="Prof" jdbcType="VARCHAR" property="prof"/>
<result column="Depart" jdbcType="VARCHAR" property="depart"/>
<collection property="student"
ofType="com.qjj.demo.entity.Student"
resultMap="com.qjj.consumer.mapper.StudentMapper.BaseResultMap"/>
</resultMap>
<select id="getAll" resultMap="GetAllMap">
select *
from teacher t
left join student s on t.classs = s.classs
<where>
<if test="param2.size != null">
and s.size <![CDATA[ <= ]]> #{param2.size}
</if>
<if test="param2.classs != null and param2.classs != ''">
and t.classs = #{param2.classs}
</if>
<if test="param2.sname != null and param2.sname != ''">
and s.Sname = #{param2.sname}
</if>
<if test="param2.tname != null and param2.tname != ''">
and t.Tname = #{param2.tname}
</if>
</where>
</select>
5、測試一(不傳任何條件,只分頁)
測試結(jié)果應(yīng)該是二條數(shù)據(jù),總數(shù)是四條
@RestController
@RequestMapping("/demo")
public class DemoController {
@Resource
private TeacherMapper teacherMapper;
@PostMapping("/test3")
public Page<TeacherVO> getAll(TeacherRequestVo teacherRequestVo) {
Page<TeacherVO> teacherVOPage = new Page<>(1, 2);
return teacherMapper.getAll(teacherVOPage, teacherRequestVo);
}
}

{
"records": [
{
"classs": "804",
"tname": "李誠",
"tsex": "男",
"tbirthday": "1958-12-02 00:00:00",
"prof": "副教授",
"depart": "計算機系",
"student": [
{
"sno": "108",
"sname": "丘東",
"ssex": "男",
"sbirthday": "1977-09-01 00:00:00",
"classs": null
},
{
"sno": "105",
"sname": "匡明",
"ssex": "男",
"sbirthday": "1975-10-02 00:00:00",
"classs": null
}
]
}
],
"total": 4,
"size": 2,
"current": 1,
"orders": [],
"optimizeCountSql": true,
"searchCount": true,
"countId": null,
"maxLimit": null,
"pages": 2
}
5.1、結(jié)果總結(jié)
1、總條數(shù)正確
2、頁數(shù)正確
3、數(shù)據(jù)不正確,返回條數(shù)不正確,應(yīng)該返回兩條數(shù)據(jù),但現(xiàn)在只返回了一條
5.2、結(jié)果分析
查看它最終指向的sql語句
找到在
SimpleExecutor下的doQuery方法。

總條數(shù)的sql語句為:
SELECT COUNT(*) AS total FROM teacher t
分頁語句為:
select *
from teacher t
left join student s on t.classs = s.classs LIMIT 2
拿去數(shù)據(jù)庫運行結(jié)果為:

至此可以看出它只是獲取了同一個老師下兩個不同的學(xué)生信息;
而不是我們想象的兩個老師,分別對應(yīng)多個學(xué)生;
但總條數(shù)和條數(shù)正確
6、測試二(傳兩個表的條件)

得到的結(jié)果應(yīng)該是一個老師對應(yīng)他下面的兩個學(xué)生
總條數(shù)是1
總數(shù)是1
6.1、測試結(jié)果
{
"records": [
{
"classs": "804",
"tname": "李誠",
"tsex": "男",
"tbirthday": "1958-12-02 00:00:00",
"prof": "副教授",
"depart": "計算機系",
"student": [
{
"sno": "108",
"sname": "丘東",
"ssex": "男",
"sbirthday": "1977-09-01 00:00:00",
"classs": null,
"size": 1
},
{
"sno": "105",
"sname": "匡明",
"ssex": "男",
"sbirthday": "1975-10-02 00:00:00",
"classs": null,
"size": 2
}
]
}
],
"total": 2,
"size": 2,
"current": 1,
"orders": [],
"optimizeCountSql": true,
"searchCount": true,
"countId": null,
"maxLimit": null,
"pages": 1
}
6.2、結(jié)果總結(jié)
總條數(shù)不對
頁數(shù)雖然對,但是那是因為我們分頁的數(shù)量是2,而學(xué)生表中正好是一個老師對應(yīng)兩個學(xué)生,所以才對,但只要當一個老師對應(yīng)3個學(xué)生或者超過2的話,頁數(shù)也就不會對了,這里就不給大家測試了,大家可以自行測試一下
數(shù)據(jù)雖然看起來對的,但是跟頁數(shù)是一樣的道理,其實是錯的
6.3、結(jié)果分析
還是查看它最終執(zhí)行的SQL語句:
發(fā)現(xiàn)執(zhí)行查詢總條數(shù)的SQL語句有問題
SELECT COUNT(*) AS total FROM teacher t LEFT JOIN student s ON t.classs = s.classs WHERE s.size <= 3 AND t.classs = '804'
二、解決
在上面的測試中發(fā)現(xiàn)兩個問題
1、數(shù)據(jù)不對
2、條數(shù)和頁數(shù)不對
1、沒條件查詢只分頁
我們修改
xxxMapper.xml中的resultMap采用級聯(lián)查詢
<resultMap id="GetAllMap" type="com.qjj.demo.entity.vo.TeacherVO">
<!--@mbg.generated-->
<!--@Table teacher-->
<result column="classs" jdbcType="VARCHAR" property="classs"/>
<result column="Tname" jdbcType="VARCHAR" property="tname"/>
<result column="Tsex" jdbcType="VARCHAR" property="tsex"/>
<result column="Tbirthday" jdbcType="TIMESTAMP" property="tbirthday"/>
<result column="Prof" jdbcType="VARCHAR" property="prof"/>
<result column="Depart" jdbcType="VARCHAR" property="depart"/>
<collection property="student"
ofType="com.qjj.demo.entity.Student1"
column="classs"
select="getStudent"/>
</resultMap>
<select id="getAll" resultMap="GetAllMap">
select t.*
from teacher t
left join student s on t.classs = s.classs
<where>
<if test="param2.size != null">
and s.size <![CDATA[ <= ]]> #{param2.size}
</if>
<if test="param2.classs != null and param2.classs != ''">
and t.classs = #{param2.classs}
</if>
<if test="param2.sname != null and param2.sname != ''">
and s.Sname = #{param2.sname}
</if>
<if test="param2.tname != null and param2.tname != ''">
and t.Tname = #{param2.tname}
</if>
</where>
</select>
<select id="getStudent" resultMap="com.qjj.demo.mapper.Student1Mapper.BaseResultMap">
select *
from student
where classs = #{classs}
</select>

{
"records": [
{
"classs": "804",
"tname": "李誠",
"tsex": "男",
"tbirthday": "1958-12-02 00:00:00",
"prof": "副教授",
"depart": "計算機系",
"student": [
{
"sno": "108",
"sname": "丘東",
"ssex": "男",
"sbirthday": "1977-09-01 00:00:00",
"classs": null,
"size": 1
},
{
"sno": "105",
"sname": "匡明",
"ssex": "男",
"sbirthday": "1975-10-02 00:00:00",
"classs": null,
"size": 2
}
]
},
{
"classs": "804",
"tname": "李誠",
"tsex": "男",
"tbirthday": "1958-12-02 00:00:00",
"prof": "副教授",
"depart": "計算機系",
"student": [
{
"sno": "108",
"sname": "丘東",
"ssex": "男",
"sbirthday": "1977-09-01 00:00:00",
"classs": null,
"size": 1
},
{
"sno": "105",
"sname": "匡明",
"ssex": "男",
"sbirthday": "1975-10-02 00:00:00",
"classs": null,
"size": 2
}
]
}
],
"total": 4,
"size": 2,
"current": 1,
"orders": [],
"optimizeCountSql": true,
"searchCount": true,
"countId": null,
"maxLimit": null,
"pages": 2
}
2、兩個表都有條件

{
"records": [
{
"classs": "804",
"tname": "李誠",
"tsex": "男",
"tbirthday": "1958-12-02 00:00:00",
"prof": "副教授",
"depart": "計算機系",
"student": [
{
"sno": "108",
"sname": "丘東",
"ssex": "男",
"sbirthday": "1977-09-01 00:00:00",
"classs": null,
"size": 1
},
{
"sno": "105",
"sname": "匡明",
"ssex": "男",
"sbirthday": "1975-10-02 00:00:00",
"classs": null,
"size": 2
}
]
},
{
"classs": "804",
"tname": "李誠",
"tsex": "男",
"tbirthday": "1958-12-02 00:00:00",
"prof": "副教授",
"depart": "計算機系",
"student": [
{
"sno": "108",
"sname": "丘東",
"ssex": "男",
"sbirthday": "1977-09-01 00:00:00",
"classs": null,
"size": 1
},
{
"sno": "105",
"sname": "匡明",
"ssex": "男",
"sbirthday": "1975-10-02 00:00:00",
"classs": null,
"size": 2
}
]
}
],
"total": 2,
"size": 2,
"current": 1,
"orders": [],
"optimizeCountSql": true,
"searchCount": true,
"countId": null,
"maxLimit": null,
"pages": 1
}
3、結(jié)果總結(jié)
無條件時
數(shù)量正確,數(shù)據(jù)重復(fù),頁數(shù)正確
兩表都有條件時:
總數(shù)不對,數(shù)據(jù)重復(fù),頁數(shù)不正確
4、結(jié)果分析
查看最終sql語句
查詢總條數(shù)的SQL語句:
SELECT COUNT(*) AS total FROM teacher t LEFT JOIN student s ON t.classs = s.classs WHERE s.size <= ? AND t.classs = ?
查詢老師表的SQL語句:
select t.*
from teacher t
left join student s on t.classs = s.classs
WHERE s.size <= 3
and t.classs = "804" LIMIT 2
去數(shù)據(jù)庫執(zhí)行發(fā)現(xiàn)查詢老師表的sql語句查出兩條相同結(jié)果
其實到這里很多人都知道怎么解決了,只要去除重復(fù)的數(shù)據(jù),所有問題都可以解決,無論是用去重,還是GROUP BY都可以實現(xiàn),我下面采用GROUP BY
5、最終方案
加上
GROUP BY進行去重,其他地方都沒改動
<select id="getAll" resultMap="GetAllMap">
select t.classs,
t.Tname,
t.Tsex,
t.Tbirthday,
t.Prof,
t.Depart
from teacher t
left join student s on t.classs = s.classs
<where>
<if test="param2.size != null">
and s.size <![CDATA[ <= ]]> #{param2.size}
</if>
<if test="param2.classs != null and param2.classs != ''">
and t.classs = #{param2.classs}
</if>
<if test="param2.sname != null and param2.sname != ''">
and s.Sname = #{param2.sname}
</if>
<if test="param2.tname != null and param2.tname != ''">
and t.Tname = #{param2.tname}
</if>
</where>
GROUP BY t.classs
</select>
5.1、坑
進行分組的字段必須是主鍵,不然會報錯
這里就不給大家展示測試結(jié)果了,沒必要了,大家可自行測試
到這里問題完美解決
三、結(jié)束語
本人寫過的所有解決什么問題都是項目中花了超過1個多小時才解決的問題,希望這篇文章對同學(xué)們有所幫助,不喜勿噴,有任何問題都可以評論,最后送上我的兩句座右銘:
任何人都不會在意你成功的過程,只在意你成功的結(jié)果,在你沒有成功之前,切勿向別人強調(diào)過程;
請不要假裝努力,結(jié)果不會陪你演戲;
到此這篇關(guān)于Mybatis-Plus或PageHelper多表分頁查詢總條數(shù)不對問題的解決方法的文章就介紹到這了,更多相關(guān)Mybatis-Plus多表分頁查詢總條數(shù)不對內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
IntelliJ IDEA像Eclipse一樣打開多個項目的圖文教程
這篇文章主要介紹了IntelliJ IDEA像Eclipse一樣打開多個項目的方法圖文教程講解,需要的朋友可以參考下2018-03-03
java8新特性之stream的collect實戰(zhàn)教程
這篇文章主要介紹了java8新特性之stream的collect實戰(zhàn)教程,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-08-08
Springboot+Netty+Websocket實現(xiàn)消息推送實例
這篇文章主要介紹了Springboot+Netty+Websocket實現(xiàn)消息推送實例,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02

