Selaa lähdekoodia

fix 优化后台管理代充列表返回速度

zoujiajian 3 päivää sitten
vanhempi
sitoutus
dcd21926fd

+ 83 - 26
netflix-web/src/main/java/com/cyksj/web/controller/manage/group/CmsGroupRelationController.java

@@ -54,9 +54,13 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.util.ArrayList;
 import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 /**
@@ -196,36 +200,89 @@ public class CmsGroupRelationController {
         SearchResult<GroupsRelationRechargeView> search = beanSearcher.search(GroupsRelationRechargeView.class, builder
                 .field(GroupsRelationRechargeView::getStatus, List.of(GroupsRelation.Status.validity.name(), GroupsRelation.Status.outside.name())).op(Operator.InList)
                 .build());
-        search.getDataList().forEach(data -> {
-            // Ticket-slot ownership is authoritative for multi-quantity orders. Resolve it
-            // before the legacy relation_id lookup, otherwise an old/generated relation order
-            // can mask the real multi-quantity parent order.
-            OrderDon orderDon = null;
-            OrderDonTicketRecord ticketRecord = orderDonTicketRecordMapper.selectOne(
-                    Wrappers.lambdaQuery(OrderDonTicketRecord.class)
-                            .eq(OrderDonTicketRecord::getRelationId, data.getRelationId())
-                            .eq(OrderDonTicketRecord::getStatus, OrderDonTicketRecord.Status.success)
-                            .orderByDesc(OrderDonTicketRecord::getId)
-                            .last("limit 1"));
-            if (ticketRecord != null) {
-                OrderDon slotOrder = orderDonMapper.selectById(ticketRecord.getOrderId());
-                if (slotOrder != null && !Constant.noOrderAllStatus.contains(slotOrder.getStatus())) {
-                    orderDon = slotOrder;
-                }
+        fillRechargeOrderNos(search.getDataList());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+    }
+
+    /**
+     * Fill order numbers in batches. The old implementation issued up to three SQL statements
+     * for every row on the page, which made a ten-row page perform 20-30 database round trips.
+     */
+    private void fillRechargeOrderNos(List<GroupsRelationRechargeView> dataList) {
+        if (CollUtil.isEmpty(dataList)) {
+            return;
+        }
+
+        List<Long> relationIds = dataList.stream()
+                .map(GroupsRelationRechargeView::getRelationId)
+                .filter(Objects::nonNull)
+                .distinct()
+                .collect(Collectors.toList());
+        if (relationIds.isEmpty()) {
+            return;
+        }
+
+        // Ticket-slot ownership is authoritative. Keep only the latest successful slot per relation,
+        // matching the previous "order by id desc limit 1" behavior.
+        Map<Long, OrderDonTicketRecord> latestTicketByRelation = new HashMap<>();
+        orderDonTicketRecordMapper.selectList(Wrappers.lambdaQuery(OrderDonTicketRecord.class)
+                        .select(OrderDonTicketRecord::getId, OrderDonTicketRecord::getRelationId,
+                                OrderDonTicketRecord::getOrderId)
+                        .in(OrderDonTicketRecord::getRelationId, relationIds)
+                        .eq(OrderDonTicketRecord::getStatus, OrderDonTicketRecord.Status.success)
+                        .orderByDesc(OrderDonTicketRecord::getId))
+                .forEach(record -> latestTicketByRelation.putIfAbsent(record.getRelationId(), record));
+
+        Set<Long> ticketOrderIds = latestTicketByRelation.values().stream()
+                .map(OrderDonTicketRecord::getOrderId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+        Map<Long, OrderDon> ticketOrderById = ticketOrderIds.isEmpty()
+                ? new HashMap<>()
+                : orderDonMapper.selectBatchIds(ticketOrderIds).stream()
+                .collect(Collectors.toMap(OrderDon::getId, order -> order, (left, right) -> left));
+
+        Set<Long> resolvedRelationIds = new HashSet<>();
+        dataList.forEach(data -> {
+            OrderDonTicketRecord ticket = latestTicketByRelation.get(data.getRelationId());
+            OrderDon order = ticket == null ? null : ticketOrderById.get(ticket.getOrderId());
+            if (order != null && !Constant.noOrderAllStatus.contains(order.getStatus())) {
+                data.setOrderNo(order.getOrderNo());
+                resolvedRelationIds.add(data.getRelationId());
             }
-            if (orderDon == null) {
-                orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class)
-                        .eq(OrderDon::getUserId, data.getUserId())
-                        .eq(OrderDon::getRelationId, data.getRelationId())
+        });
+
+        List<GroupsRelationRechargeView> unresolved = dataList.stream()
+                .filter(data -> data.getRelationId() != null && !resolvedRelationIds.contains(data.getRelationId()))
+                .collect(Collectors.toList());
+        if (unresolved.isEmpty()) {
+            return;
+        }
+
+        List<Long> unresolvedRelationIds = unresolved.stream()
+                .map(GroupsRelationRechargeView::getRelationId).distinct().collect(Collectors.toList());
+        List<Long> userIds = unresolved.stream()
+                .map(GroupsRelationRechargeView::getUserId).filter(Objects::nonNull)
+                .distinct().collect(Collectors.toList());
+        if (userIds.isEmpty()) {
+            return;
+        }
+
+        Map<String, OrderDon> latestLegacyOrder = new HashMap<>();
+        orderDonMapper.selectList(Wrappers.lambdaQuery(OrderDon.class)
+                        .in(OrderDon::getRelationId, unresolvedRelationIds)
+                        .in(OrderDon::getUserId, userIds)
                         .notIn(OrderDon::getStatus, Constant.noOrderAllStatus)
-                        .orderByDesc(OrderDon::getId)
-                        .last("limit 1"));
-            }
-            if (orderDon != null) {
-                data.setOrderNo(orderDon.getOrderNo());
+                        .orderByDesc(OrderDon::getId))
+                .forEach(order -> latestLegacyOrder.putIfAbsent(
+                        order.getRelationId() + ":" + order.getUserId(), order));
+
+        unresolved.forEach(data -> {
+            OrderDon order = latestLegacyOrder.get(data.getRelationId() + ":" + data.getUserId());
+            if (order != null) {
+                data.setOrderNo(order.getOrderNo());
             }
         });
-        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
     }
 
     /**