mybatis <collection>标签使用及分页数量问题解决

MyBatis <collection>标签查询及分页问题解决
博客围绕查询酒店订单集合及详情展开,最初做法查询效率低,后采用MyBatis <collection>标签实现一次查询。试验发现方式二效率更高。但使用该标签出现分页数量不对问题,分析是将内部数据当成一条记录分页所致,提出用子查询解决,期望有更优方案。
  • 场景:

​ 最近做查询酒店订单集合时,需要把酒店订单详情也查出来,酒店订单表 和 酒店订单详情表 是一对多的关系(用订单编号进行关联);最初的做法是 :先去查询酒店订单集合 再循环查询酒店订单详情集合。这么做相当于一次查询要循环执行多次查询,会导致查询效率异常的慢。

​ 所以想找一种方式 一次查询出酒店订单集合并且直接将酒店订单详情集合作为list 封装进结果集。于是想到了 <collection>标签。

  • 部分代码及DO类:

    订单DO类(其余无关字段已省略):

    public class TicketOrderAndDetailDO {
    
        private Integer id;
        private String orderAmount;//订单金额
        private String orderNum;
        private List<TicketOrderDetailDO> details;//订单详情集合
    }
    

    订单详情DO类(其余无关字段已省略):

    public class TicketOrderDetailDO {
    
        private Integer id;
        private String orderDetailId;//订单明细编号
        private String orderNum;//订单编号
    }
    

    <collection> 有两种使用方式:

    方式一:

    <!-- 这种用法依旧相当于循环执行sql 效率低下,不使用 -->
    <resultMap id="RM-TicketOrderAndDetail" type="TicketOrderAndDetailDO">
        <result column="t_id" property="id"/>
        <result column="order_amount" property="orderAmount"/>
        <result column="order_num" property="orderNum"/>
        <collection property="details" ofType="TicketOrderDetailDO" column="order_num" javaType="list"
                    select="com.dhzhly.core.order.persistence.dao.TicketOrderDetailMapper.queryListByOrderNum">
        </collection>
    </resultMap>
    

    方式二:

    <resultMap id="RM-TicketOrderAndDetail3" type="TicketOrderAndDetailDO">
        <result column="t_order_num" property="orderNum"/>
        <result column="t_id" property="id"/>
        <result column="t_order_amount" property="orderAmount"/>
    
        <collection property="details" ofType="TicketOrderDetailDO" javaType="list">
            <result column="d_order_num" property="orderNum"/>
            <result column="d_id" property="id"/>
            <result column="d_order_detail_id" property="orderDetailId"/>
        </collection>
    </resultMap>
    

    经过试验发现,方式一 虽然和数据库只建立了一次连接 但是 还是执行了查询sql 性能不高,所以不使用;而方式二 只执行了一次sql 效率要搞很多,所以选择方式二。

  • <collection>导致的分页数量问题:

    使用<collection>标签确实实现了一对多的一次查询,但是遇到一个新的问题:分页数量不对。我们项目未使用分页插件,看网友反馈 使用pagehelper及mybatis plus插件的也遇到了这个问题。

    现在就 自己手写sql 来分析下为什么会出现数量不对以及如何解决:

    • 分页数量为什么不对?

      类似下面这种常规的分页sql:

      ​ select * from table where … limit 0,10

      使用<collection>封装结果集时,会把内部的数据当成一条记录进行分页,例如上面的例子 有2个订单,每个订单有2个订单详情,本来订单数量应该是2 ,而这种情况下 会统计为4。这就导致分页的数量出现问题。

    • 解决方法:

      使用子查询:

      ​ 思路:使用子查询 查询出符合条件的 外部数据(即酒店订单)对其进行分页 ,之后再去关联查询内部数据(即酒店详情订单),这样查询出来的外部数据(即酒店订单)的数量就对了。

      <select id="getMerchantHotelOrderList" parameterType="MerchantHotelOrderQuery" resultMap="RM-TicketOrderAndDetail3">
              SELECT
              t.id t_id,
              t.order_amount t_order_amount,
              t.order_num t_order_num,
              d.id d_id,
              d.order_detail_id d_order_detail_id,
              d.order_num d_order_num,
              from
              (
                  select * from
                  ticket_order
                  where
                  order_num in
                  (
                      select
                      t1.order_num
                      from
                      ticket_order_detail d1
                      inner join
                      ticket_order t1
                      on
                      d1.order_num = t1.order_num
                      <where>
                          <!-- where 条件省略 -->
                      </where>
                  ) order by id desc
                  <trim>
                      <if test="pageSize!=null and pageIndex!=null">
                          limit #{offset},#{limit}
                      </if>
                  </trim>
              ) t
              left join
              ticket_order_detail d
              on
              d.order_num = t.order_num
          </select>
      

对于分页数量问题的解决,应该还有其他更优的方案,还望指教。

2. (单选题) MyBatis 中的 Mapper 接口是做什么用的? A 定义数据库表结构 B 定义 SQL 语句 C 定义事务管理 D 定义业务逻辑 3. (单选题) 在 MyBatis 中,哪个标签用于定义一条查询语句? A <select> B <insert> C <update> D <delete> 4. (单选题) MyBatis 支持的动态 SQL 元素不包括以下哪个? A <if> B <choose> C <when> D <for> 5. (单选题) MyBatis 中,哪个配置元素用于定义数据库连接信息? A <dataSource> B <transactionManager> C <environments> D <mappers> 6. (单选题) MyBatis 中,哪个配置元素用于定义结果映射? A <resultMap> B <parameterMap> C <sqlMap> D <mapper> 7. (单选题) MyBatis 中,哪个配置元素用于定义多个数据库环境? A <environments> B <dataSource> C <mappers> D <transactionManager> 8. (单选题) MyBatis 中,哪个配置元素用于定义 MyBatis 映射文件的位置? A <mappers> B <environments> C <dataSource> D <transactionManager> 9. (单选题) MyBatis 支持的结果集类型不包括以下哪个? A list B map C xml D array 10. (单选题) MyBatis 中,哪个配置元素用于定义 MyBatis 插件? A <plugins> B <environments> C <dataSource> D <mappers> 11. (单选题) MyBatis 支持的日志实现不包括以下哪个? A SLF4J B LOG4J C LOG4J2 D JULL 12. (单选题) MyBatis 中,哪个配置元素用于定义 MyBatis 的日志实现? A <settings> B <environments> C <dataSource> D <logImpl> 13. (单选题) MyBatis 中,哪个配置元素用于定义 MyBatis 属性文件的位置? A <properties> B <propertyFiles> C <configFile> D <settings> 14. (单选题) PageHelper 分页插件是通过什么机制来实现分页的? A 拦截器(Interceptor) B AOP C JDBC D XML 15. (单选题) MyBatisX 是一款基于哪个IDE的快速开发插件? A Eclipse B IntelliJ IDEA C NetBeans D Visual Studio Code 16. (单选题) 在 MyBatis 中,使用分页插件后,以下哪个操作会导致分页不生效? A 在查询之前调用 PageHelper.startPage(pageNum, pageSize); B 在查询之后调用 PageHelper.startPage(pageNum, pageSize); C 使用 PageInfo 对象封装查询结果 D 使用 Page 对象封装查询结果 17. (单选题) MyBatisX 插件的安装步骤中,以下哪个步骤不是必需的? A 在 IDEA 中安装 MybatisX 插件 B 在 pom.xml 文件中引入 MyBatis-Plus 依赖 C 在 application.yml 中配置数据库连接 D 在数据库中创建视图 18. (单选题) 在MyBatis的动态SQL中,<if> 标签的作用是什么? A 仅当指定条件为真时执行内部的SQL语句 B 无条件地执行内部的SQL语句 C 循环执行内部的SQL语句 D 将多个SQL语句合并为一个 19. (单选题) MyBatis中 <foreach> 标签collection 属性是用来遍历哪个类型的参数? A 单个值 B 数组 C 集合 D 映射 20. (单选题) 在MyBatis中,<set> 标签用于构建哪个SQL语句的部分? A SELECT B INSERT C UPDATE D DELETE 21. (单选题) 在MyBatis中,如果要实现多对一查询,通常使用哪个标签来定义结果映射? A <collection> B <association> C <result> D <sql> 22. (单选题) 当使用MyBatis进行一对多查询时,以下哪个标签用于定义结果映射中的集合属性? A <association> B <collection> C <result> D <sql> 23. (单选题) 在MyBatis中,如果要通过嵌套查询实现多表关联查询,通常需要在哪个标签中定义子查询? A <association> B <collection> C <resultMap> D <select> 24. (单选题) 在MyBatis中,如果要实现分页关联查询,通常会使用哪个插件来辅助实现? A PageHelper B MyBatisX C MyBatis-Spring D MyBatis-Plus 25. (单选题) MyBatis 允许在 XML 映射文件中使用哪种标签来包含其他 SQL 片段? A <include> B <import> C <file> D <sql>
10-18
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值