• 浅析Mybatis一对多与PageHelper产生的问题


    一、问题记录

      在 mybatis 中使用 collection 映射一对多关系的结果集时,会存在2个问题:

    1、问题一:total总数与实际返回数量不一致

    2、问题二:实际返回数据有问题

    二、Mybatis一对多的两种mapper写法

      Mybatis提供了两种一对多的解决方案:一种是嵌套结果,一种是嵌套查询

    1、嵌套结果查询:

      多表关联查询出一对一的关系,再封装成Teacher对象

    <select id="getTeacher" resultMap="TeacherMap">
        select t.id id, t.name tname, s.id sid, s.name sname, s.tid tid
        from teacher t
        left join student s
        on t.id = s.tid
    </select>
    
    <resultMap type="Teacher" id="TeacherMap">
        <result property="id" column="id"/>
        <result property="name" column="tname"/>
        <collection property="students" ofType="Student">
            <result property="id" column="sid"/>
            <result property="name" column="sname"/>
            <result property="tid" column="tid"/>
        </collection>
    </resultMap>

    2、嵌套查询

      先查出Teacher对象,再遍历匹配出相应的Student对象集合

    <select id="xxx" resultMap="TeacherMap">
        select id, name from teacher
    </select>
    
    <select id="selectStudents" resultType="Student">
        select id, tid, name from student
    </select>
    
    <resultMap type="Teacher" id="TeacherMap">
        <result property="id" column="id"/>
        <result property="name" column="name"/>
        <collection property="students" ofType="Student" select="selectStudents"column="id" javaType="java.util.List">
            <result property="id" column="id"/>
            <result property="tid" column="tid"/>
            <result property="name" column="name"/>
        </collection>
    </resultMap>

    三、问题剖析

    1、方法一采用关联查询的方式查询数据。

    select t.id id, t.name tname, s.id sid, s.name sname, s.tid tid
    from teacher t
    left join student s
    on t.id = s.tid

      查询结果如下4条

    image.png

      如果使用PageHelper,会在以上sql种拼接limit,这样产生的影响是:

    (1)对 total 的影响

      因为老师只有2个,我们需要的返回total是2,但是由于多表关联查出来的是以上结果,那么total就会返回4,导致total错误,进而导致页面分页也有问题

    (2)对返回结果的影响

    • 如果pagesize >= 4,那所有结果均返回,并且会生成Teacher对象,返回两条结果。没问题
    • 如果pagesize < 4, 比如是2,那李老师就被limit掉了,返回结果只有张老师一个人。有问题

      问题原因:因为 teacher 和 student 表是一对多的关系,所以在关联查询时,虽然是查出来了 4 条记录,但是这 4 条记录中,teacher 有重复的(因为一个 teacher 有多个学生)。而这些记录在封装成 Student 对象返回前端时,会按 Student 进行逐个封装,这样就会出现数量减少的情况。

    2、方法二首先执行了如下sql

    select id, name from teacher

      查询结果2条

    image.png

      如果使用PageHelper,会在以上sql种拼接limit

    (1)关于 total

      由于pageHelper只会对紧接着的第一个sql起作用,因此total返回2,没问题

    (2)关于返回结果

      PageHelper不会影响后面的sql,因此,不影响结果。没问题

      所以在使用 pageHelper 加一对多的映射时,尽量选用“嵌套查询”的方式。

  • 相关阅读:
    Markdown随手记
    主成分分析法(离散K-L变换)
    JAVAV EMAIL
    IDEA使用mybatis-generator
    java画海报二维码
    官网网址 学习指南
    Socket的用法——NIO包下SocketChannel的用法 ———————————————— 版权声明:本文为CSDN博主「茶_小哥」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/ycgslh/article/details/79604074
    Java NIO ———— Buffer 缓冲区详解 入门
    JVM类加载机制详解(二)类加载器与双亲委派模型
    mysql索引数据结构
  • 原文地址:https://www.cnblogs.com/goloving/p/14882543.html
Copyright © 2020-2023  润新知