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

  • 场景:

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

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

  • 部分代码及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;//订单编号
    }
    

    有两种使用方式:

    方式一:

    
    <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 效率要搞很多,所以选择方式二。

  • 导致的分页数量问题:

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

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

    • 分页数量为什么不对?

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

      ​ select * from table where … limit 0,10

      使用封装结果集时,会把内部的数据当成一条记录进行分页,例如上面的例子 有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>
                  ) 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>
      

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

你可能感兴趣的:(mysql,java,mybatis,sql)