ruoyi中 mybatis 一对多以及pageHelper分页问题

kk / 2024-04-18 / 原文

问题

  1. mybatis 如何进行一对多映射
  2. mybatis 分页时无法获取的totalCount数据不对,总等于pageSize

需要返回的结果

public class OrderOutput {
    private Long totalNum;// 当前订单所有总数
    private Long orderTotalPrice;// 当前订单所有产品总价
    @JsonFormat(shape = JsonFormat.Shape.STRING)
    @JSONField(serializeUsing = ToStringSerializer.class)
    private Long orderId; // 当前订单编号
    private Date createTime;// 订单时间
    private Integer orderStatus;
    private List<OrderDto> orderItems; // 订单详单
}


public class OrderDto {
    private Long id;
    private Long uid;
    private Long pnum;
    private Long totalPrice;
    private String uname;
    private String pname;
    private Long price;
}

当前接口的需求是,返回订单list,并且每个item中的有订单详单,并且需要实现分页查询。
当前订单需要统计所有详单中的订单产品总数,以及每一个所有产品的累计金额。

实现

Service

在Service中,调用mapper方法,并统计订单总金额以及总数量

List<OrderOutput> orderOutputs = orderIdsMapper.selectOrderIds(new OrderIds());

orderOutputs.forEach(x -> {
            List<OrderDto> orderItems = x.getOrderItems();
            long totalPrice = 0L;
            Long totalNum = 0L;

            for (OrderDto orderItem : orderItems) {
                totalPrice += orderItem.getPnum() *orderItem.getPrice();
                totalNum += orderItem.getPnum();
            }

            x.setTotalNum(totalNum);
            x.setOrderTotalPrice(totalPrice);
            result.add(x);
        });

Mapper xml

在mapper中分别定义OrderOutput的resultMap以及List中的OrderDto的resultMap,并把orderDto的resultMap作为orderREsultMap的子查询结果。
同时,分别写两个select查询,传参可以参考下面xml,多个传参在column中param1=a,param2=b

<resultMap id="orderREsultMap" type="OrderOutput">
        <id property="orderId" column="orderId" />
        <result property="createTime" column="createTime" />
        <result property="orderStatus" column="orderStatus" />
        <collection property="orderItems"
                    ofType="OrderDto"
                    select="getOrderDtoById"
                    column="{id=orderId}"
                    javaType="java.util.List"
        >

        </collection>
    </resultMap>

    <resultMap id="OrderDtoMap" type="OrderDto">
        <id property="id" column="id"/>
        <result property="uid" column="uid"/>
        <result property="uname" column="uname"/>
        <result property="pnum" column="pnum"/>
        <result property="totalPrice" column="totalPrice"/>
    </resultMap>

<!--    子查询-->
    <select id="getOrderDtoById" resultMap="OrderDtoMap">
        select o.uid,o.uname,o.pnum,o.total_price
        from orders o
        where o.order_id = #{id}<!-- id对应上面collection中的column -->
    </select>

<!--    主查询-->
    <select id="selectOrderIds" resultMap="orderREsultMap">
        select
            oi.id as orderId,
            oi.create_time as createTime,
            oi.order_status as orderStatus
        from
            order_ids oi
    </select>

Controller

    @PreAuthorize("@ss.hasPermi('danchen_system:orders:list')")
    @GetMapping("/list")
    public TableDataInfo list() {
        startPage();
        List<OrderOutput> orderList = ordersService.GetOrdersList();
        return getDataTable(orderList);
    }

ruoyi-vue使用startPage对数据进行分页,使用的是PageHelper,但是通过返回数据发现,获取到的total为list的数量,例如原本不分页之前数据量为13,分页之后返回的数据量为10,也就是前端请求数据是的pagesize大小。

参考文档说是破坏了PageInfo的完整性,将service中的循环处理逻辑删除之后进行验证,发现返回total数已经正确了,说明确实是这部分出错了。

解决

要继续使用ruoyi的startPage进行分页,并且不破坏原来的数据完整性,根据若依官网后台分页逻辑的介绍,只对该语句以后的第一个查询(Select)语句得到的数据进行分页。,因此等数据分页完整之后,再对数据进行处理即可,接口修改如下

Controller

public TableDataInfo list() {
        startPage();
        List<OrderOutput> orderList = ordersService.GetOrdersList();
        orderList.forEach(x -> {
            List<OrderDto> orderItems = x.getOrderItems();
            long totalPrice = 0L;
            Long totalNum = 0L;

            for (OrderDto orderItem : orderItems) {
//                totalPrice += orderItem.getPnum() *orderItem.getPrice();
                totalNum += orderItem.getPnum();
            }

            x.setTotalNum(totalNum);
            x.setOrderTotalPrice(totalPrice);
        });
        return getDataTable(orderList);
    }

Service

public List<OrderOutput> GetOrdersList() {
        return orderIdsMapper.selectOrderIds(new OrderIds());
    }

将原来在Service的处理逻辑,在Controller中实现