前言

项目老大说项目需要重构搜索功能,决定交给我这个比较闲的人! 嗯 ???

因为以前的项目数据不大,都不能说不大,是很少,所有搜索采用的是MySQL中的like模糊搜索操作的,他希望我改一下;

我第一时间想到了ES,但他说没必要用ES,等以后数据量大了再换,现在只是稍微多了一些数据,没必要

Ok!那我就用了MySQL自带的全文检索功能,因为本文主要说的还是Mybatis-Plus的问题,所以全文检索在下面只会提到怎么使用,以及一些问题

好像说了一大堆废话,回归正题!

项目以前分页搜索用的是PageHelper这个插件,但公司封装的3.0框架中已经封装了Mybatis-Plus,所以我采用了Mybatis-Plus的分页插件

一、问题说明

场景:

老师表是有4条数据,每个老师对应2个学生

使用的是两个表联查letf joinMybatis的级联查询,一次性获取所有数据出现3个问题:

1、数据总条数以及页数不对

2、数据分页数量不对

3、数据混乱

已下是我有问题的代码:

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);
        //当超过最大页数时不会报错
        pii.setOverflow(true);
        return pii;
    }
}

3、创建mapper层

创建了一个返回实体类TeacherVO,包括老师信息以及学生信息,以及一个传入的参数类TeacherRequestVo

@Data
public class TeacherVO {
     /**
     * 跟学生表关联的字段
     */
    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> {
    /**
     * 获取老师所带班级中的所有老师及学生信息
     * @param page mybatisplus自带的page类
     * @param teacherRequestVo 传入的参数
     * @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、测试一(不传任何条件,只分页)

测试结果应该是二条数据,总数是四条

@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、结果总结

1、总条数正确

2、页数正确

3、数据不正确,返回条数不正确,应该返回两条数据,但现在只返回了一条

5.2、结果分析

查看它最终指向的sql语句

找到在SimpleExecutor下的doQuery方法。

总条数的sql语句为:

SELECT COUNT(*) AS total FROM teacher t

分页语句为:

select *
   from teacher t
       left join student s on t.classs = s.classs LIMIT 2

拿去数据库运行结果为:

至此可以看出它只是获取了同一个老师下两个不同的学生信息

而不是我们想象的两个老师,分别对应多个学生;

但总条数和条数正确

6、测试二(传两个表的条件)

得到的结果应该是一个老师对应他下面的两个学生

总条数是1

总数是1

6.1、测试结果

{
    "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、结果总结

总条数不对

页数虽然对,但是那是因为我们分页的数量是2,而学生表中正好是一个老师对应两个学生,所以才对,但只要当一个老师对应3个学生或者超过2的话,页数也就不会对了,这里就不给大家测试了,大家可以自行测试一下

数据虽然看起来对的,但是跟页数是一样的道理,其实是错的

6.3、结果分析

还是查看它最终执行的SQL语句:

发现执行查询总条数的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'

二、解决

在上面的测试中发现两个问题

1、数据不对

2、条数和页数不对

1、没条件查询只分页

我们修改xxxMapper.xml中的resultMap采用级联查询

  <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、结果总结

无条件时

数量正确,数据重复,页数正确

两表都有条件时:

总数不对,数据重复,页数不正确

4、结果分析

查看最终sql语句

查询总条数的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

去数据库执行发现查询老师表的sql语句查出两条相同结果

其实到这里很多人都知道怎么解决了,只要去除重复的数据,所有问题都可以解决,无论是用去重,还是GROUP BY都可以实现,我下面采用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、坑

进行分组的字段必须是主键,不然会报错

这里就不给大家展示测试结果了,没必要了,大家可自行测试

到这里问题完美解决

三、结束语

本人写过的所有解决什么问题都是项目中花了超过1个多小时才解决的问题,希望这篇文章对同学们有所帮助,不喜勿喷,有任何问题都可以评论,最后送上我的两句座右铭:

任何人都不会在意你成功的过程,只在意你成功的结果,在你没有成功之前,切勿向别人强调过程;

请不要假装努力,结果不会陪你演戏;

到此这篇关于Mybatis-Plus或PageHelper多表分页查询总条数不对问题的解决方法的文章就介绍到这了,更多相关Mybatis-Plus多表分页查询总条数不对内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

Mybatis-Plus或PageHelper多表分页查询总条数不对问题的解决方法的更多相关文章

  1. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  2. MybatisPlus中的多表条件排序查询

    这篇文章主要介绍了MybatisPlus中的多表条件排序查询,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. Mybatis详解动态SQL以及单表多表查询的应用

    MyBatis的动态SQL是基于OGNL表达式的,它可以帮助我们方便的在SQL语句中实现某些逻辑,下面这篇文章主要给大家介绍了关于Mybatis超级强大的动态SQL语句的相关资料,需要的朋友可以参考下

  4. 解决mybatis分页插件PageHelper导致自定义拦截器失效

    这篇文章主要为大家介绍了解决mybatis分页插件PageHelper导致自定义拦截器失效方案示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  5. jsp+mysql实现网页的分页查询

    这篇文章主要为大家详细介绍了jsp+mysql实现网页的分页查询,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  6. MyBatis 多表联合查询及优化方法

    大家都知道Hibernate 是全自动的数据库持久层框架,它可以通过实体来映射数据库,通过设置一对多、多对一、一对一、多对多的关联来实现联合查询,接下来通过本文给大家介绍MyBatis 多表联合查询及优化,需要的朋友可以参考下

  7. MyBatis实现多表联查的详细代码

    这篇文章主要介绍了MyBatis如何实现多表联查,通过实例代码给大家介绍使用映射配置文件实现多表联查,使用注解的方式实现多表联查,需要的朋友可以参考下

  8. pagehelper分页工具类的封装

    这篇文章主要为大家详细介绍了pagehelper分页工具类的封装,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  9. js如何使用Pagination+PageHelper实现分页

    本文主要介绍了js如何使用Pagination+PageHelper实现分页,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  10. EJB 3.0开发指南之多表映射

    事实上,一个实体Bean可以映射到多张表上。假如你使用多张表,你可以使用下面的注释来声明多张表:@SecondaryTable@Target@Retentionpublic@interfaceSecondaryTables{SecondaryTable[]value()default{};}这个例子主要有以下几个文件,这个例子主要实现了管理学生的功能。学生的性别映射到第二张表中。和前面的例子一样,我们还是使用Client测试。StudentDAO.java:会话Bean的业务接口StudentDAOBea

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部