小鹏汽车智慧材料数据库系统项目总成数据同步

news2024/11/25 20:44:31

1、定时任务处理

2、提供了接口

小鹏方面提供的推送的数据表结构:

这几个表总数为100多万,经过条件筛选过滤后大概2万多条数据

小鹏的人给的示例图:

界面:

SQL:

-- 查询车型
select bmm.md_material_id, bmm.material_num, bmm.material_name, bmm.material_name_en
from bm_md_material bmm
where bmm.md_material_id in
      (SELECT bpa.master_part_id
       from (SELECT bpa.master_part_id, bpa.sub_part_id FROM bm_part_assembly bpa WHERE bpa.bom_type = 'PART') a
                INNER JOIN bm_part_assembly bpa on bpa.sub_part_id = a.master_part_id AND bpa.bom_type = 'EBOM');


# 根据车型材料id(md_material_id)总成主数据
select
bpa.bm_part_assembly_id as bmPartAssemblyId,
bpa.master_part_id as master_part_id,
bpa.sub_part_id as sub_part_id,
bpa.update_date as update_date,
bpa.quantity as useNumber,
bpa.weight_tag as weight,
bpa.dev_type as developStatus,
bpa.employee_id as bomResponsibleEngineer,
bpa.suggest_sourcing as procurementType,
bpa.bom_type,
bpa.change_id,
bpae.importance_level severity,
bpae.torque as tighteningTorque,
bpae.note as connectionsCodeZhDescribe,
bpae.vehicleproject as inheritedRemodeledModels,
bmm.material_num
from bm_part_assembly bpa
    left join bm_part_assembly_ext bpae on bpae.bm_part_assembly_ext_id = bpa.part_assembly_ext_id
    inner join bm_md_material bmm on bmm.md_material_id = bpa.sub_part_id
where (bpa.bom_type = 'EBOM' or bpa.bom_type = 'PART')
         and is_latest = 1 -- 最新版本
         and active_status = 'current' -- 生效状态
         and bpa.update_date > '2024-07-01'
#          and bpa.master_part_id = '98535' -- 车型 md_material_id 23821, 根据 sub_part_id  4010809DF1-00-03 64332   车型的  23821
         and bpa.master_part_id = '23821' -- 车型 md_material_id 23821, 根据 sub_part_id  4010809DF1-00-03 64332   车型的  23821
#          and bpa.master_part_id = '98532' -- 车型 md_material_id 23821, 根据 sub_part_id  4010809DF1-00-03 64332   车型的  23821
#          and bpa.master_part_id = '193598' -- 车型 md_material_id 23821, 根据 sub_part_id  4010809DF1-00-03 64332   车型的  23821
         and bpa.master_part_id = '64332' -- 车型 md_material_id 23821, 根据 sub_part_id  4010809DF1-00-03 64332   车型的  23821   如:根据子件id:64332查询,递归去查询,直到无下级
#          and bpa.sub_part_id like '64332'
         and material_num = '4010809DF1-00-03'
;

Mapper和Mapper.xml

<!-- 总成主数据 -->
    <select id="syncDataByPage" resultType="com.ruiyada.whole.domain.vo.BomAssemblyVo">
        select
        bpa.bm_part_assembly_id as syncPartAssemblyId,
        bpa.master_part_id as masterPartId, -- 父件id(父物料id)
        bpa.sub_part_id as subPartId, -- 子件id(子物料id)
        bpa.update_date as lastSyncUpdateDate,  -- 同步版本号
        bpa.quantity as useNumber, -- 用量
        bpa.weight_tag as weight, -- 重量
        bpa.dev_type as developStatus, -- 开发状态
        bpa.employee_id as employeeId, -- 员工id 根据这个员工id去员工表查询 责任工程师
        bpa.suggest_sourcing as procurementType, -- 采购类型
        bpa.bom_type as bomType,
        bpa.change_id as changeId,
        bpae.importance_level as severity, -- 重要度
        bpae.torque as tighteningTorque, -- 紧固力矩
        bpae.note as connectionsCodeZhDescribe, -- 连接点代码中文描述
        bpae.vehicleproject as inheritedRemodeledModels
        from bm_part_assembly bpa
            left join bm_part_assembly_ext bpae on bpae.bm_part_assembly_ext_id = bpa.part_assembly_ext_id
            inner join bm_md_material bmm on bmm.md_material_id = bpa.sub_part_id
        where (bpa.bom_type = 'EBOM' or bpa.bom_type = 'PART')
        and is_latest = 1 -- 最新版本
        and active_status = 'current'
        <if test="lastSyncUpdateDate!='' and lastSyncUpdateDate!=null">
            and bpa.update_date &gt; #{lastSyncUpdateDate}
        </if>
        <if test="masterPartId!='' and masterPartId!=null">
            and bpa.master_part_id = #{masterPartId}
        </if>
        ORDER BY bpa.update_date DESC
        LIMIT #{start}, #{pageSize}
    </select>

    <!-- 车型数据 -->
    <select id="selectCarData" resultType="com.ruiyada.whole.domain.vo.BomAssemblyVo">
        select bmm.md_material_id as materielId,
               bmm.material_num as materielCode,
               bmm.material_name as materielCnName,
               bmm.material_name_en as materielEnName
        from bm_md_material bmm
        where bmm.md_material_id in (SELECT bpa.master_part_id from
            (SELECT  bpa.master_part_id, bpa.sub_part_id FROM bm_part_assembly bpa
                                                         WHERE bpa.bom_type  = 'PART') a
                INNER JOIN bm_part_assembly bpa on bpa.sub_part_id  = a.master_part_id AND bpa.bom_type  = 'EBOM')
    </select>

    <!-- BOM责任工程师 -->
    <select id="bomResponsibleEngineer" resultType="com.ruiyada.whole.domain.vo.BomAssemblyVo">
        select bau.user_id userId,
               bau.user_name userName,
               bau.organization_id organizationId
        from bm_acct_user bau where user_id = #{employeeId};
    </select>

    <!-- 责任部门 -->
    <select id="bomResponsibleDepartment" resultType="com.ruiyada.whole.domain.vo.BomAssemblyVo">
        select
            bao.id as orgId, bao.org_name as bomResponsibleDepartment, bao.org_name_en as orgNameEn
        from bm_acct_organization bao
        where id = #{organizationId}
    </select>

    <!--生效ECN编号-->
    <select id="selectEcnNumberEffect" resultType="string">
        select bmc.change_code AS ecnNumberEffect
        from bm_md_change bmc where md_change_id = #{changeId}
    </select>

    <!-- 查询已同步的最新的一条版本号 -->
    <select id="selectLastSyncUpdateDate" resultType="java.time.LocalDateTime">
        select DATE_FORMAT(last_sync_update_time, '%Y-%m-%d') as last_sync_update_time from bom_assembly_material_parts order by last_sync_update_time desc limit 1;
    </select>

    <!-- 根据物料id查询总成下级 -->
    <select id="selectByMaterialId" resultType="com.ruiyada.whole.domain.vo.BomAssemblyVo">
        select bmm.md_material_id as materielId,
               bmm.material_name as materielCnName,
               bmm.material_name_en as materielEnName,
               bmm.material_num as materielCode
        from  bm_md_material bmm
        where md_material_id in
        <foreach item="item" index="index" collection="materialIds" open="(" separator="," close=")">
            #{item}
        </foreach>
    </select>

    <!-- 统计车型下的总成总数 -->
    <select id="assentlyCount" resultType="java.lang.Integer">
        select
            count(1)
        from bm_part_assembly bpa
                 left join bm_part_assembly_ext bpae on bpae.bm_part_assembly_ext_id = bpa.part_assembly_ext_id
                 inner join bm_md_material bmm on bmm.md_material_id = bpa.sub_part_id
        where (bpa.bom_type = 'EBOM' or bpa.bom_type = 'PART')
          and is_latest = 1 -- 最新版本
          and active_status = 'current' -- 生效状态
          and bpa.master_part_id = #{masterPartId}
    </select>
@Mapper
public interface BomAssemblyMaterialPartsMapper extends BaseMapper<BomAssemblyMaterialParts> {


    List<BomAssembyMaterialPartsVO> ListById(@Param("bom_id") String bomId);

    /**
     * 查询已同步的最新的一条版本号
     */
    LocalDateTime selectLastSyncUpdateDate();

    /**
     * 分页查询总成主数据
     * @param start
     * @param pageSize
     * @param lastSyncUpdateDate
     * @return
     */
    List<BomAssemblyVo> syncDataByPage(@Param("start") int start, @Param("pageSize") int pageSize,
                                       @Param("lastSyncUpdateDate") String lastSyncUpdateDate,
                                       @Param("masterPartId") String masterPartId);

    /**
     * 车型数据
     * @return
     */
    List<BomAssemblyVo>  selectCarData();

    /**
     * BOM责任工程师
     * @return
     */
    BomAssemblyVo  bomResponsibleEngineer(@Param("employeeId") String employeeId);

    /**
     * 责任部门
     * @return
     */
    BomAssemblyVo  bomResponsibleDepartment(@Param("organizationId") String organizationId);

    /**
     * 生效ECN编号
     * @return
     */
    String  selectEcnNumberEffect(@Param("changeId") String changeId);

    /**
     * 根据物料id查询总成下级数据
     * @param materialIds
     * @return
     */
    List<BomAssemblyVo>  selectByMaterialId(@Param("materialIds") List<String> materialIds);

    /**
     * 统计车型下的总成总数
     * @param masterPartId
     * @return
     */
    Integer assentlyCount(@Param("masterPartId") String masterPartId);

}
/**
 * <p>
 * BOM总成材料零件表 服务实现类
 * </p>
 *
 * @author 袁腾飞
 * @since 2024-10-14
 */
@Slf4j
@Service
public class BomAssemblyMaterialPartsServiceImpl extends ServiceImpl<BomAssemblyMaterialPartsMapper, BomAssemblyMaterialParts> implements BomAssemblyMaterialPartsService {

    @Autowired
    private BomAssemblyMaterialPartsMapper bomAssemblyMaterialPartsMapper;

    @Autowired
    private BomCategoryService bomCategoryService;
@Override
    public List<BomAssemblyMaterialParts> syncDataByPage(int pageSize) {
        // 获取上一次同步数据的更新时间
        LocalDateTime lastSyncUpdateDate = selectLastSyncUpdateDate();
        String formatLastSyncUpdateDate = lastSyncUpdateDate==null ? "" : lastSyncUpdateDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        // 组装数据
        List<BomAssemblyDto> bomAssemblyDtos = assemblingData(pageSize, formatLastSyncUpdateDate);
        // 把组装后的数据转换为BomAssemblyMaterialParts对象
        // bomAssemblyDtos在里面取出每个字段
        // bomAssemblyDtos的父级,给BomAssemblyMaterialParts对象父级设置parentId为0,id自动生成;里层的children的parentId为外层的id
        // 父级的parentId设为0
        List<BomAssemblyMaterialParts> partsList = convertToBomAssemblyMaterialParts(bomAssemblyDtos, "0");
        // partsList里面的children取出与父节点一起保存
        if (!partsList.isEmpty()) {
            bomAssemblyMaterialPartSaveBatch(partsList);
        }
        return partsList;
    }

    private void bomAssemblyMaterialPartSaveBatch(List<BomAssemblyMaterialParts> partsList) {
        // 收集所有需要保存的节点
        List<BomAssemblyMaterialParts> allNodes = collectAllNodes(partsList);
        // 批量插入所有节点

        // 判断allNodes里面的syncPartAssemblyId是否在数据库中存在,如果不存在,则插入,如果存在,则更新
        // List<String> list = allNodes.stream().map(BomAssemblyMaterialParts::getSyncPartAssemblyId).collect(Collectors.toList());
        allNodes.stream().map(item -> item).forEach(item -> {
            // 判断item是否在数据库中存在
            LambdaQueryWrapper<BomAssemblyMaterialParts> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(BomAssemblyMaterialParts::getSyncPartAssemblyId, item.getSyncPartAssemblyId());
            BomAssemblyMaterialParts bomAssemblyMaterialParts = bomAssemblyMaterialPartsMapper.selectOne(queryWrapper);
            if (bomAssemblyMaterialParts == null) {
                // 不存在,则插入
                bomAssemblyMaterialPartsMapper.insert(item);
            } else {
                // 存在,则更新
                bomAssemblyMaterialPartsMapper.update(item, queryWrapper);
            }
        });
        // bomAssemblyMaterialPartsMapper.insertOrUpdate(allNodes);
    }

    private List<BomAssemblyMaterialParts> collectAllNodes(List<BomAssemblyMaterialParts> nodes) {
        List<BomAssemblyMaterialParts> allNodes = new ArrayList<>();
        for (BomAssemblyMaterialParts node : nodes) {
            allNodes.add(node);
            if (node.getChildren() != null && !node.getChildren().isEmpty()) {
                allNodes.addAll(collectAllNodes(node.getChildren()));
            }
        }
        return allNodes;
    }

    private List<BomAssemblyDto> convertToBomAssemblyDtos(List<BomAssemblyVo> bomAssemblyVos, String ecnNumberEffect) {
        if (bomAssemblyVos == null || bomAssemblyVos.isEmpty()) {
            return Collections.emptyList();
        }
        return bomAssemblyVos.stream()
                .map(vo -> {
                    BomAssemblyDto dto = new BomAssemblyDto();
                    BeanUtils.copyProperties(vo, dto);
                    dto.setChildren(convertToBomAssemblyDtos(vo.getChildren(), ecnNumberEffect));
                    return dto;
                })
                .collect(Collectors.toList());
    }

    private List<BomAssemblyMaterialParts> convertToBomAssemblyMaterialParts(List<BomAssemblyDto> dtos, String parentId) {
        List<BomAssemblyMaterialParts> collect = dtos.stream().map(dto -> {
            String id = "";

            // 判断item是否在数据库中存在
            LambdaQueryWrapper<BomAssemblyMaterialParts> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(BomAssemblyMaterialParts::getSyncPartAssemblyId, dto.getSyncPartAssemblyId());
            BomAssemblyMaterialParts bomAssemblyMaterialParts = bomAssemblyMaterialPartsMapper.selectOne(queryWrapper);
            if (bomAssemblyMaterialParts == null) {
                // 不存在,则就生成id
                id = IdUtil.simpleUUID();
            } else {
                // 存在,id 和 parentId 保持不变
                id = bomAssemblyMaterialParts.getId();
            }
            BomAssemblyMaterialParts parts = new BomAssemblyMaterialParts();
            String bomCategoryId = dto.getBomCategoryId();
            BeanUtils.copyProperties(dto, parts);
            parts.setId(id);
            parts.setParentId(parentId);
            parts.setBomId(bomCategoryId);
            List<BomAssemblyDto> children = dto.getChildren();
            if (!children.isEmpty()) {
                List<BomAssemblyMaterialParts> partsList = convertToBomAssemblyMaterialParts(dto.getChildren(), parts.getId());
                // 这里的partList里面的数据bomId没有给赋值,需要给bomId赋值:bomCategoryId
                // parts.setBomId(bomCategoryId);
                partsList.forEach(part -> part.setBomId(bomCategoryId));
                parts.setChildren(partsList);
            }
            parts.setLastSyncUpdateTime(dto.getLastSyncUpdateDate());
            parts.setCreateTime(LocalDateTime.now());
            parts.setUpdateTime(LocalDateTime.now());
            return parts;
        }).collect(Collectors.toList());
        return collect;
    }

    /**
     * 组装数据
     *
     * @param pageSize          每页大小
     * @param lastSyncVersionNo 上一次同步的版本号
     * @return
     */
    private List<BomAssemblyDto> assemblingData(int pageSize, String lastSyncVersionNo) {
        // 先查询车型
        List<BomAssemblyVo> selectedCarData = selectCarData();
        // todo 暂时过滤一下数据,只查询一个车型
        // List<BomAssemblyVo> collect = selectedCarData.stream().filter(bomAssemblyVo -> bomAssemblyVo.getMaterielId().equals("23821")).collect(Collectors.toList());
        // 构建 md_material_id 到 BomAssemblyVo 的映射
        Map<String, BomAssemblyVo> carDataMap = selectedCarData.stream().collect(Collectors.toMap(BomAssemblyVo::getMaterielId, vo -> vo));
        // Map<String, BomAssemblyVo> carDataMap = collect.stream().collect(Collectors.toMap(BomAssemblyVo::getMaterielId, vo -> vo));
        /*
            步骤:
            1、先是查询出基础总成数据
            2、先查询车型,拿到车型的md_material_id
            3、根据拿到每个车型的md_material_id 查询 bm_part_assembly表的master_part_id,就得到了得到sub_part_id
            4、得到sub_part_id 查询bm_md_material表,得到了下级总成,循环类推,递归
            5、查询的下级放在BomAssemblyVo里面的children集合里面
            6、拼装数据,把查询生效ECN编号、
            数据量很大,100多万数据
            能不能用stream流、递归、树形结构
            select bmm.md_material_id as materialId, bmm.material_name materielName, bmm.material_num from  bm_md_material bmm
            where md_material_id in #{materialId}
         */

        List<BomAssemblyDto> result = new ArrayList<>();
        // 用carDataMap key查询数据
        carDataMap.forEach((masterPartId, value) -> {
            // 获取总数
            Integer totalCount = assentlyCount(masterPartId);
            double totalPage = Math.ceil((double) totalCount / pageSize);

            // 分页处理
            for (int currentPage = 0; currentPage < totalPage; currentPage++) {
                int offset = currentPage * pageSize;
                // 根据查询的车型的id的这个key查询获取sub_part_id,在这里bomAssemblyVos获取sub_part_id值,获得sub_part_id值后再次用bomAssemblyMaterialPartsMapper.syncDataByPage查询,把查询到的sub_part_id值传入到key的位置,直到查询不到数据
                // 第一次查询的是父节点,递归出来的后面的查询是子节点放在children里面
                List<BomAssemblyVo> bomAssemblyVos = bomAssemblyMaterialPartsMapper.syncDataByPage(offset, pageSize, lastSyncVersionNo, masterPartId);
                // todo 临时测试用
                // List<BomAssemblyVo> bomAssemblyVos = bomAssemblyVoList.stream().filter(bomAssemblyVo -> bomAssemblyVo.getSubPartId().equals("64332")).collect(Collectors.toList());
                // List<BomAssemblyVo> bomAssemblyVos = bomAssemblyVoList.stream().filter(bomAssemblyVo -> bomAssemblyVo.getSubPartId().equals("98535")).collect(Collectors.toList());
                // List<BomAssemblyVo> bomAssemblyVos = bomAssemblyVoList.stream().filter(bomAssemblyVo -> bomAssemblyVo.getSubPartId().equals("64332")).collect(Collectors.toList());

                // BOM分类车型数据
                LambdaQueryWrapper<BomCategory> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(BomCategory::getIsCar, 1);
                List<BomCategory> bomCategories = bomCategoryService.list(queryWrapper);
                // 车型名称
                String carType = value.getMaterielCnName();
                // 在这里获取所有的分类名称(categoryName)和id,如果categoryName与carType比较,
                // 如果匹配上就把bomCategories的id给BomAssemblyVo对象的bomCategoryId并保存数据,否则就不保存数据
                // 查找匹配的车型分类
                Optional<BomCategory> categoryOptional = bomCategories.stream()
                        .filter(cat -> cat.getCategoryName().equals(carType))
                        .findFirst();

                if (categoryOptional.isPresent()) {
                    String categoryId = categoryOptional.get().getId();
                    // 设置categoryId到每个BomAssemblyVo对象
                    setCategoryIdRecursively(bomAssemblyVos, categoryId);
                } else {
                    // 如果没有匹配的分类,则跳过这些数据
                    return;
                }

                // 补充 materialName 和 materialNum 对于父节点
                Set<String> parentIds = bomAssemblyVos.stream()
                        .map(BomAssemblyVo::getSubPartId)
                        .filter(Objects::nonNull)
                        .collect(Collectors.toSet());

                if (!parentIds.isEmpty()) {
                    List<BomAssemblyVo> parentDetails = selectByMaterialIds(new ArrayList<>(parentIds));
                    Map<String, BomAssemblyVo> parentDetailMap = parentDetails.stream()
                            .collect(Collectors.toMap(BomAssemblyVo::getMaterielId, vo -> vo));

                    for (BomAssemblyVo assembly : bomAssemblyVos) {
                        BomAssemblyVo detail = parentDetailMap.get(assembly.getSubPartId());
                        if (detail != null) {
                            assembly.setMaterielCnName(detail.getMaterielCnName());
                            assembly.setMaterielEnName(detail.getMaterielEnName());
                            assembly.setMaterielCode(detail.getMaterielCode());
                            assembly.setPartCode(detail.getPartCode());
                            assembly.setCarType(detail.getCarType());
                            assembly.setEcnNumberEffect(detail.getEcnNumberEffect());
                            assembly.setPartNumber(detail.getPartNumber());
                            assembly.setBomType(detail.getBomType());
                        }
                    }
                }

                // 再组装数据
                for (BomAssemblyVo assembly : bomAssemblyVos) {
                    buildTree(assembly, offset, pageSize, lastSyncVersionNo);
                    String changeId = assembly.getChangeId();
                    String changeCode = selectEcnNumberEffect(changeId);

                    String employeeId = assembly.getEmployeeId();

                    String userName = "";
                    String organizationId = "";
                    if (StringUtils.isNotBlank(employeeId)) {
                        // BOM责任工程师
                        BomAssemblyVo bomAssemblyVo = bomResponsibleEngineer(employeeId);
                        if (bomAssemblyVo != null) {
                            userName = bomAssemblyVo.getUserName();
                            organizationId = bomAssemblyVo.getOrganizationId();
                        }
                    }

                    String bomResponsibleDepartment = "";
                    if (StringUtils.isNotBlank(organizationId)) {
                        // BOM责任部门
                        BomAssemblyVo assemblyVo = bomResponsibleDepartment(organizationId);
                        if (assemblyVo != null) {
                            bomResponsibleDepartment = assemblyVo.getBomResponsibleDepartment();
                        }
                    }

                    assembly.setUserName(userName);
                    assembly.setBomResponsibleDepartment(bomResponsibleDepartment);

                    BomAssemblyDto bomAssemblyDto = new BomAssemblyDto();
                    BeanUtils.copyProperties(assembly, bomAssemblyDto);
                    bomAssemblyDto.setChildren(convertToBomAssemblyDtos(assembly.getChildren(), changeCode));
                    result.add(bomAssemblyDto);
                }
            }
        });

        log.info("result:::::::::" + result);
        // 拼装数据,包括生效ECN编号等信息
        // convertToBomAssemblyMaterialParts(result);
        return result;
    }

    private void setCategoryIdRecursively(List<BomAssemblyVo> bomAssemblyVos, String categoryId) {
        for (BomAssemblyVo assembly : bomAssemblyVos) {
            assembly.setBomCategoryId(categoryId);
            if (assembly.getChildren() != null && !assembly.getChildren().isEmpty()) {
                setCategoryIdRecursively(assembly.getChildren(), categoryId);
            }
        }
    }

    private void buildTree(BomAssemblyVo parent, int pageNo, int pageSize, String lastSyncVersionNo) {
        if (parent == null || parent.getSubPartId() == null) {
            return;
        }

        List<BomAssemblyVo> children = bomAssemblyMaterialPartsMapper.syncDataByPage(pageNo, pageSize, lastSyncVersionNo, parent.getSubPartId());

        // 补充 materialName 和 materialNum
        Set<String> subPartIds = children.stream()
                .map(BomAssemblyVo::getSubPartId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());

        if (!subPartIds.isEmpty()) {
            List<BomAssemblyVo> materialDetails = selectByMaterialIds(new ArrayList<>(subPartIds));
            Map<String, BomAssemblyVo> materialDetailMap = materialDetails.stream()
                    .collect(Collectors.toMap(BomAssemblyVo::getMaterielId, vo -> vo));

            for (BomAssemblyVo child : children) {
                BomAssemblyVo detail = materialDetailMap.get(child.getSubPartId());
                if (detail != null) {
                    child.setMaterielCnName(detail.getMaterielCnName());
                    child.setMaterielEnName(detail.getMaterielEnName());
                    child.setMaterielCode(detail.getMaterielCode());
                    child.setPartCode(detail.getPartCode());
                    child.setCarType(detail.getCarType());
                    child.setEcnNumberEffect(detail.getEcnNumberEffect());
                    child.setPartNumber(detail.getPartNumber());
                    child.setBomType(detail.getBomType());
                }
            }
        }

        parent.setChildren(children);
        for (BomAssemblyVo child : children) {
            buildTree(child, pageNo, pageSize, lastSyncVersionNo);
        }
    }

    /**
     * 查询车型
     *
     * @return
     */
    private List<BomAssemblyVo> selectCarData() {
        List<BomAssemblyVo> list = bomAssemblyMaterialPartsMapper.selectCarData();
        return list;
    }

    /**
     * 查询生效ECN编号
     *
     * @return
     */
    private String selectEcnNumberEffect(String changeId) {
        return bomAssemblyMaterialPartsMapper.selectEcnNumberEffect(changeId);
    }

    /**
     * 根据物料id查询总成下级数据
     *
     * @param materialIds
     * @return
     */
    private List<BomAssemblyVo> selectByMaterialIds(List<String> materialIds) {
        /*
            这个sql是这样的:select bmm.md_material_id as materialId, bmm.material_name materielName, bmm.material_num from  bm_md_material bmm
            where md_material_id in #{materialIds}
         */
        if (materialIds == null || materialIds.isEmpty()) {
            return Collections.emptyList();
        }
        return bomAssemblyMaterialPartsMapper.selectByMaterialId(materialIds);
    }

    /**
     * BOM责任工程师
     *
     * @return
     */
    private BomAssemblyVo bomResponsibleEngineer(String employeeId) {
        return bomAssemblyMaterialPartsMapper.bomResponsibleEngineer(employeeId);
    }

    /**
     * BOM责任部门
     *
     * @param organizationId
     * @return
     */
    private BomAssemblyVo bomResponsibleDepartment(String organizationId) {
        return bomAssemblyMaterialPartsMapper.bomResponsibleDepartment(organizationId);
    }

    /**
     * 同步版本号
     *
     * @return
     */
    private LocalDateTime selectLastSyncUpdateDate() {
        LocalDateTime lastSyncUpdateDate = bomAssemblyMaterialPartsMapper.selectLastSyncUpdateDate();
        log.info("最新版本号:{}", lastSyncUpdateDate);
        return lastSyncUpdateDate;
    }

    @Override
    public Integer assentlyCount(String masterPartId) {
        Integer assentlyCount = bomAssemblyMaterialPartsMapper.assentlyCount(masterPartId);
        return assentlyCount == null ? 0 : assentlyCount;
    }

}
/**
 * <p>
 * BOM总成材料零件表 服务类
 * </p>
 *
 * @author 袁腾飞
 * @since 2024-10-14
 */
public interface BomAssemblyMaterialPartsService extends IService<BomAssemblyMaterialParts> {

    IPage<BomAssemblyMaterialParts> pageListCondition(PagingQuery pagingQuery, BomAssemblyQuery queryParam);

    List<BomAssembyMaterialPartsVO> ListById(String bomId);

    List<BomAssemblyMaterialParts> listCondition(PagingQuery pagingQuery, BomAssemblyQuery queryParam);

    List<BomAssemblyMaterialParts> syncDataByPage(int pageSize);

    Integer assentlyCount(String masterPartId);
}

定时任务层

/**
 * 同步总成数据
 */
@Slf4j
@Lazy(value = false)
@Component
// @PropertySource(value = "classpath:jobTask.properties",encoding = "UTF-8")
public class SyncWholeData {

    @Autowired
    private BomAssemblyMaterialPartsService bomAssemblyMaterialPartsService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Value("${pageSize}")
    private Integer pageSize;

    /**
     * 同步总成数据
     */
    @Transactional(rollbackFor = Exception.class)
    @Async
    @Scheduled(cron = "${inactiveaccountCron}")
    public void syncWhole1() {
        String lockKey = "lock:sync:whole:";
        boolean isLocked = tryLock(lockKey);
        try {
            if (isLocked) {
                // 成功获取锁,执行同步逻辑
                bomAssemblyMaterialPartsService.syncDataByPage(pageSize);
            }
        } finally {
            unlock(lockKey);
        }
    }

    /**
     * 尝试获取锁
     *
     * @param key
     * @return
     */
    private boolean tryLock(String key) {
        // setIfAbsent 如果存在
        Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(key, "1", 2, TimeUnit.HOURS);
        return BooleanUtil.isTrue(flag);
    }

    /**
     * 释放锁
     *
     * @param key
     */
    private void unlock(String key) {
        stringRedisTemplate.delete(key);
    }

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2247483.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【解决方案】VITE 忽略指定路径的资源

前言 问题起因是因为项目需要引入服务器端的网络图片 而在编写配置时发现&#xff0c;Vite并不支持排除指定前缀的资源 唯一可以排外的只有 Rollup 的 external 选项可以排除外部依赖&#xff0c;但他只能排除外部依赖&#xff0c;不支持指定路径资源或指定前缀的资源&#…

自然语言处理: RAG优化之Embedding模型选型重要依据:mteb/leaderboard榜

本人项目地址大全&#xff1a;Victor94-king/NLP__ManVictor: CSDN of ManVictor git地址&#xff1a;https://github.com/opendatalab/MinerU 写在前面: 笔者更新不易&#xff0c;希望走过路过点个关注和赞&#xff0c;笔芯!!! 写在前面: 笔者更新不易&#xff0c;希望走过路…

疑难Tips:NextCloud域名访问登录时卡住,显示违反内容安全策略

[ 知识是人生的灯塔,只有不断学习,才能照亮前行的道路 ] 1使用域名访问Nextcloud用户登录时卡住,显示违反内容安全策略 我使用官方Docker镜像来部署NextCloud 28.0.5,并通过Openresty反向代理Nextcloud,但是在安装后无法稳定工作,每次登录后,页面会卡死在登录界面,无法…

SpringBoot 集成 html2Pdf

一、概述&#xff1a; 1. springboot如何生成pdf&#xff0c;接口可以预览可以下载 2. vue下载通过bold如何下载 3. 一些细节&#xff1a;页脚、页眉、水印、每一页得样式添加 二、直接上代码【主要是一个记录下次开发更快】 模板位置 1. 导入pom包 <dependency><g…

java实现小程序接口返回Base64图片

文章目录 引言I java 接口返回Base64图片接口设计获取验证码图片-base64字符串获取验证码图片-二进制流arraybufferII 小程序端代码过期代码: 显示文件流图片(arraybuffer)知识扩展:微信小程序下载后端返回的文件流引言 场景: 图形验证码 背景: 接口返回arraybuffer的格式…

Pytorch自定义算子反向传播

文章目录 自定义一个线性函数算子如何实现反向传播 有关 自定义算子的实现前面已经提到&#xff0c;可以参考。本文讲述自定义算子如何前向推理反向传播进行模型训练。 自定义一个线性函数算子 线性函数 Y X W T B Y XW^T B YXWTB 定义输入M 个X变量&#xff0c;输出N个…

ajax (一)

什么是 AJAX [ˈeɪdʒks] &#xff1f; 概念&#xff1a;AJAX是浏览器与服务器进行 数据通信 的技术&#xff0c;动态数据交互 怎么用AJAX? 1. 先使用 axios [k‘sio ʊ s] 库&#xff0c; 与服务器进行 数据通信 ⚫ 基于 XMLHttpRequest 封装、代码简单、月下载量在 1…

URL在线编码解码- 加菲工具

URL在线编码解码 打开网站 加菲工具 选择“URL编码解码” 输入需要编码/解码的内容&#xff0c;点击“编码”/“解码”按钮 编码&#xff1a; 解码&#xff1a; 复制已经编码/解码后的内容。

魔众题库系统 v10.0.0 客服条、题目导入、考试导航、日志一大批更新

魔众题库系统基于PHP开发&#xff0c;可以用于题库管理和试卷生成软件&#xff0c;拥有极简界面和强大的功能&#xff0c;用户遍及全国各行各业。 魔众题库系统发布v10.0.0版本&#xff0c;新功能和Bug修复累计30项&#xff0c;客服条、题目导入、考试导航、日志一大批更新。 …

深入解析 EasyExcel 组件原理与应用

✨深入解析 EasyExcel 组件原理与应用✨ 官方&#xff1a;EasyExcel官方文档 - 基于Java的Excel处理工具 | Easy Excel 官网 在日常的 Java 开发工作中&#xff0c;处理 Excel 文件的导入导出是极为常见的需求。 今天&#xff0c;咱们就一起来深入了解一款非常实用的操作 Exce…

本地部署 MaskGCT

本地部署 MaskGCT 0. 更新系统和安装依赖项1. 克隆代码2. 创建虚拟环境3. 安装依赖模块4. 运行 MaskGCT5. 访问 MaskGCT 0. 更新系统和安装依赖项 sudo apt update sudo apt install espeak-ng1. 克隆代码 git clone https://github.com/engchina/learn-maskgct.git; cd lear…

线程控制方法之wait和sleep的区别

线程控制方法之wait和sleep的区别 wait()和sleep()都是Java线程控制方法&#xff0c;但存在明显区别&#xff1a; 所属与调用&#xff1a;wait()属Object类&#xff0c;需synchronized调用&#xff1b;sleep()属Thread类&#xff0c;可随意调用。锁处理&#xff1a;wait()释放…

Fakelocation Server服务器/专业版 Centos7

前言:需要Centos7系统 Fakelocation开源文件系统需求 Centos7 | Fakelocation | 任务一 更新Centos7 &#xff08;安装下载不再赘述&#xff09; sudo yum makecache fastsudo yum update -ysudo yum install -y kernelsudo reboot//如果遇到错误提示为 Another app is curre…

探索 RocketMQ:企业级消息中间件的选择与应用

一、关于RocketMQ RocketMQ 是一个高性能、高可靠、可扩展的分布式消息中间件&#xff0c;它是由阿里巴巴开发并贡献给 Apache 软件基金会的一个开源项目。RocketMQ 主要用于处理大规模、高吞吐量、低延迟的消息传递&#xff0c;它是一个轻量级的、功能强大的消息队列系统&…

基于信创环境的信息化系统运行监控及运维需求及策略

随着信息技术的快速发展和国家对信息安全的日益重视&#xff0c;信创环境&#xff08;信息技术应用创新环境&#xff09;的建设已成为行业发展的重要趋势。本指南旨在为运维团队在基于信创环境的系统建设及运维过程中提供参考&#xff0c;确保项目顺利实施并满足各项技术指标和…

初学 flutter 问题记录

windows搭建flutter运行环境 一、运行 flutter doctor遇到的问题 Xcmdline-tools component is missingRun path/to/sdkmanager --install "cmdline-tools;latest"See https://developer.android.com/studio/command-line for more details.1&#xff09;cmdline-to…

【虚拟机】VMWare的CentOS虚拟机断电或强制关机出现问题

VMware 虚拟机因为笔记本突然断电故障了&#xff0c;开机提示“Entering emergency mode. Exit the shell to continue.”&#xff0c;如下图所示&#xff1a; 解决方法&#xff1a;输入命令&#xff1a; xfs_repair -v -L /dev/dm-0 注&#xff1a;报 no such file or direct…

设计模式:6、装饰模式(包装器)

目录 0、定义 1、装饰模式包含的四种角色 2、装饰模式的UML类图 3、示例代码 0、定义 动态地给对象添加一些额外的职责。就功能来说装饰模式相比生成子类更为灵活。 1、装饰模式包含的四种角色 抽象组件&#xff08;Component&#xff09;&#xff1a;抽象组件是一个抽象…

Java开发经验——Spring Test 常见错误

摘要 本文详细介绍了Java开发中Spring Test的常见错误和解决方案。文章首先概述了Spring中进行单元测试的多种方法&#xff0c;包括使用JUnit和Spring Boot Test进行集成测试&#xff0c;以及Mockito进行单元测试。接着&#xff0c;文章分析了Spring资源文件扫描不到的问题&am…

Java基于Spring Boot框架的房屋租赁系统,附源码

博主介绍&#xff1a;✌Java老徐、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&…