材料站供应平衡

This commit is contained in:
mashuai 2025-09-28 23:33:28 +08:00
parent 91515b24e8
commit aed825e462
4 changed files with 64 additions and 34 deletions

View File

@ -185,4 +185,7 @@ public class MaterialProvideNumInfo {
private String endTime;
private String unitValue;
@ApiModelProperty(value = "协议id")
private String agreementIds;
}

View File

@ -266,4 +266,7 @@ public class MaterialRetainedEquipmentInfo {
@ApiModelProperty(value = "工程集合")
private List<MaterialRetainedEquipmentInfo> proNameList;
@ApiModelProperty(value = "协议id")
private String agreementIds;
}

View File

@ -1328,39 +1328,57 @@ public class MaterialMachineServiceImpl implements MaterialMachineService {
return recordList;
}
// 1. 过滤数据保留原逻辑使用并行流加速大集合过滤
// 1. 过滤数据并行流加速大集合过滤
if (teamData != null) {
recordList = recordList.parallelStream() // 并行流适合大集合过滤
recordList = recordList.parallelStream()
.filter(item -> StringUtils.isBlank(item.getIdCard()) || username.equals(item.getIdCard()))
.collect(Collectors.toList());
}
// 2. 提取批量查询的关键参数工程ID + typeId避免重复创建对象
// 2. 转换参数将agreementIds逗号字符串转为List<String>
List<Map<String, Object>> queryParams = recordList.stream()
.map(record -> {
Map<String, Object> param = new HashMap<>(2);
Map<String, Object> param = new HashMap<>(3);
param.put("proId", record.getProId());
param.put("typeId", record.getTypeId());
// 逗号分隔的agreementIds转为List
String agreementIds = record.getAgreementIds();
if (StringUtils.isNotBlank(agreementIds)) {
List<String> agreementIdList = Arrays.asList(agreementIds.split(","));
param.put("agreementIds", agreementIdList);
} else {
param.put("agreementIds", Collections.emptyList());
}
return param;
})
.collect(Collectors.toList());
// 3. 批量查询核心优化2次查询替代N次循环查询减少99%+的数据库交互
// 3.1 批量查询领料数据构建映射key=projectId_typeIdvalue=businessNum
Map<String, BigDecimal> leaseBusinessMap = materialMachineMapper.batchQueryLeaseDemand(queryParams).stream()
.collect(Collectors.toMap(
info -> getCompositeKey(info.getProId(), info.getTypeId()), // 抽成方法避免重复代码
MaterialProvideNumInfo::getBusinessNum,
(existing, replacement) -> existing // 重复key保留第一个按业务需求调整
));
// 3. 核心分批处理查询参数避免数据包过大
int batchSize = 300; // 每批大小根据实际测试调整建议200-500
Map<String, BigDecimal> leaseBusinessMap = new HashMap<>(); // 最终合并结果
// 计算总批次数
int totalBatches = (int) Math.ceil((double) queryParams.size() / batchSize);
for (int i = 0; i < totalBatches; i++) {
// 计算当前批次的起止索引
int start = i * batchSize;
int end = Math.min(start + batchSize, queryParams.size());
List<Map<String, Object>> subParams = queryParams.subList(start, end);
// 分批查询
List<MaterialProvideNumInfo> batchResult = materialMachineMapper.batchQueryLeaseDemand(subParams);
// 将当前批次结果合并到总Map中
batchResult.stream()
.forEach(info -> {
String key = getCompositeKey(info.getProId(), info.getTypeId());
// 若有重复key保留第一个与原逻辑一致
leaseBusinessMap.putIfAbsent(key, info.getBusinessNum());
});
}
// 3.2 批量查询领用数据构建映射
Map<String, BigDecimal> publishBusinessMap = materialMachineMapper.batchQueryUseDemand(queryParams).stream()
.collect(Collectors.toMap(
info -> getCompositeKey(info.getProId(), info.getTypeId()),
MaterialProvideNumInfo::getBusinessNum,
(existing, replacement) -> existing
));
// 4. 并行流处理大集合计算总和并设置record的businessNum内存操作并行化
// 用数组存储四个总和比对象更高效减少gc
@ -1370,9 +1388,7 @@ public class MaterialMachineServiceImpl implements MaterialMachineService {
recordList.parallelStream().forEach(record -> {
String key = getCompositeKey(record.getProId(), record.getTypeId());
// 从Map获取数据默认0避免null
BigDecimal leaseNum = leaseBusinessMap.getOrDefault(key, BigDecimal.ZERO);
BigDecimal publishNum = publishBusinessMap.getOrDefault(key, BigDecimal.ZERO);
BigDecimal businessNum = leaseNum.add(publishNum);
BigDecimal businessNum = leaseBusinessMap.getOrDefault(key, BigDecimal.ZERO);
// 设置record的businessNum原逻辑保留
record.setBusinessNum(businessNum);

View File

@ -2015,7 +2015,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
'安全工器具'
ELSE
'施工机具'
END jiJuType
END jiJuType,
subquery1.agreementId AS agreementIds
FROM ma_type mt
LEFT JOIN (
SELECT
@ -2034,7 +2035,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
bp.imp_unit AS impUnit,
bu.bzz_idcard AS idCard,
df.project_dept AS proCenter,
sd.dept_name AS departName
sd.dept_name AS departName,
GROUP_CONCAT(DISTINCT sai.agreement_id) AS agreementId
FROM
slt_agreement_info sai
LEFT JOIN ma_type mt ON mt.type_id = sai.type_id
@ -2256,26 +2258,32 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</select>
<select id="batchQueryLeaseDemand" resultType="com.bonus.material.clz.domain.vo.MaterialProvideNumInfo">
<!-- 批量查询领料数据 -->
SELECT
bp.pro_id AS proId,
lad.type_id AS typeId,
IFNULL( sum( lad.pre_num ), 0 ) AS businessNum
IFNULL(SUM(lad.pre_num), 0) AS businessNum
FROM
lease_apply_info lai
LEFT JOIN lease_apply_details lad ON lai.id = lad.parent_id
LEFT JOIN tm_task tt ON tt.task_id = lai.task_id
LEFT JOIN tm_task_agreement tta on tta.task_id = lai.task_id
LEFT JOIN bm_agreement_info bagi on bagi.agreement_id = tta.agreement_id
LEFT JOIN tm_task_agreement tta ON tta.task_id = lai.task_id
LEFT JOIN bm_agreement_info bagi ON bagi.agreement_id = tta.agreement_id
AND bagi.`status` = '1'
LEFT JOIN bm_project bp on bp.pro_id = bagi.project_id
LEFT JOIN bm_project bp ON bp.pro_id = bagi.project_id
AND bp.del_flag = '0'
WHERE
tt.task_status IN (3, 4)
AND tt.task_type = 2
AND (bp.pro_id, lad.type_id) IN
<foreach collection="list" item="item" separator="," open="(" close=")">
(#{item.proId}, #{item.typeId})
lad.type_id IS NOT NULL -- 基础条件type_id不为空
-- 批量条件遍历list中的每个item用OR连接多个条件组
<foreach collection="list" item="item" separator="OR" open="AND (" close=")">
-- 单个item的条件typeId匹配 + agreementIds在集合中
(
lad.type_id = #{item.typeId}
AND tta.agreement_id IN (
<foreach collection="item.agreementIds" item="aid" separator=",">
#{aid} -- 遍历agreementIds集合生成IN条件
</foreach>
)
)
</foreach>
GROUP BY
bp.pro_id,