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

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);
    }

}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 3244.新增道路查询后的最短距离 II:贪心(跃迁合并)-9行py(O(n))

【LetMeFly】3244.新增道路查询后的最短距离 II&#xff1a;贪心&#xff08;跃迁合并&#xff09;-9行py&#xff08;O(n)&#xff09; 力扣题目链接&#xff1a;https://leetcode.cn/problems/shortest-distance-after-road-addition-queries-ii/ 给你一个整数 n 和一个二维…

华为无线AC+AP组网实际应用小结

之前公司都是使用的H3C的交换机、防火墙以及无线AC和AP的&#xff0c;最近优化下无线网络&#xff0c;说新的设备用华为的&#xff0c;然后我是直到要部署的当天才知道用华为设备的&#xff0c;就很无语了&#xff0c;一点准备没有&#xff0c;以下为这次的实际操作记录吧&…

Fakelocation Server服务器/专业版 Windows11

前言:需要Windows11系统 Fakelocation开源文件系统需求 Windows11 | Fakelocation | 任务一 打开 PowerShell&#xff08;以管理员身份&#xff09;命令安装 Chocolatey Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProto…

C语言基础学习:抽象数据类型(ADT)

基础概念 抽象数据类型&#xff08;ADT&#xff09;是一种数据类型&#xff0c;它定义了一组数据以及可以在这组数据上执行的操作&#xff0c;但隐藏了数据的具体存储方式和实现细节。在C语言中&#xff0c;抽象数据类型&#xff08;ADT&#xff09;是一种非常重要的概念&…

基于深度学习CNN算法的花卉分类识别系统01--带数据集-pyqt5UI界面-全套源码

文章目录 基于深度学习算法的花卉分类识别系统一、项目摘要二、项目运行效果三、项目文件介绍四、项目环境配置1、项目环境库2、环境配置视频教程 五、项目系统架构六、项目构建流程1、数据集2、算法网络Mobilenet3、网络模型训练4、训练好的模型预测5、UI界面设计-pyqt56、项目…

Bokeh实现大规模数据可视化的最佳实践

目录 引言 一、Bokeh简介 二、安装Bokeh 三、数据准备 四、性能优化 五、创建图表 六、添加交互功能 七、应用案例 八、高级技巧 九、总结 引言 在数据科学领域,数据可视化是一个至关重要的环节。通过可视化,我们可以直观地理解数据的特征和趋势,为数据分析和决策…

Easyexcel(4-模板文件)

相关文章链接 Easyexcel&#xff08;1-注解使用&#xff09;Easyexcel&#xff08;2-文件读取&#xff09;Easyexcel&#xff08;3-文件导出&#xff09;Easyexcel&#xff08;4-模板文件&#xff09; 文件导出 获取 resources 目录下的文件&#xff0c;使用 withTemplate 获…

【山大909算法题】2014-T1

文章目录 1.原题2.算法思想3.关键代码4.完整代码5.运行结果 1.原题 为带表头的单链表类Chain编写一个成员函数Reverse&#xff0c;该函数对链表进行逆序操作&#xff08;将链表中的结点按与原序相反的顺序连接&#xff09;&#xff0c;要求逆序操作就地进行&#xff0c;不分配…

[Redis#2] 定义 | 使用场景 | 安装教程 | 快!

目录 1. 定义 In-memory data structures 在内存中存储数据 2. 优点&#xff01;快 Programmability 可编程性 Extensibility 扩展性 Persistence 持久化 Clustering 分布式集群 High availability 高可用性 ⭕快速访问的实现 3. 使用场景 1.Real-time data store …

学习编程,学习中间件,学习源码的思路

01 看的多&#xff0c;内化不足 最近想复习一下编程相关的知识&#xff0c;在复习前我翻开了之前的一些笔记&#xff0c;这些笔记基本都是从书本、视频、博客等摘取记录的&#xff0c;看着这些笔记心里总结&#xff1a;看的多&#xff0c;内化不足。 02 整理大纲 为了解决这个…

hhdb数据库介绍(10-2)

集群管理 计算节点集群 集群管理主要为用户提供对计算节点集群的部署、添加、启停监控、删除等管理操作。 集群管理记录 集群管理页面显示已部署或已添加的计算节点集群信息。可以通过左上角搜索框模糊搜索计算节点集群名称进行快速查找。同时也可以通过右侧展开展开/隐藏更…

AG32既可以做MCU,也可以仅当CPLD使用

Question: AHB总线上的所有外设都需要像ADC一样&#xff0c;通过cpld处理之后才能使用? Reply: 不用。 除了ADC外&#xff0c;其他都是 mcu可以直接配置使用的。 Question: DMA和CMP也不用? Reply: DMA不用。 ADC/DAC/CMP 用。 CMP 其实配置好后&#xff0c;可以直…

贪心算法(1)

目录 柠檬水找零 题解&#xff1a; 代码&#xff1a; 将数组和减半的最少操作次数&#xff08;大根堆&#xff09; 题解&#xff1a; 代码&#xff1a; 最大数&#xff08;注意 sort 中 cmp 的写法&#xff09; 题解&#xff1a; 代码&#xff1a; 摆动序列&#xff0…

网络爬虫——综合实战项目:多平台房源信息采集与分析系统

1. 项目背景与目标 1.1 项目背景 随着房产市场的快速发展&#xff0c;各大平台上充斥着大量房源信息。为了帮助用户快速掌握市场动态&#xff0c;需要通过爬虫技术自动采集多平台数据&#xff0c;清洗后进行存储和分析&#xff0c;为用户提供有价值的洞察。开发者通过这一实战…

数据结构-7.Java. 对象的比较

本篇博客给大家带来的是java对象的比较的知识点, 其中包括 用户自定义类型比较, PriorityQueue的比较方式, 三种比较方法...... 文章专栏: Java-数据结构 若有问题 评论区见 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条. 你们的支持是我不断创作的动力 .…

NVR录像机汇聚管理EasyNVR多品牌NVR管理工具/设备如何使用Docker运行?

在当今的安防监控领域&#xff0c;随着视频监控技术的不断发展和应用范围的扩大&#xff0c;如何高效、稳定地管理并分发视频流资源成为了行业内外关注的焦点。EasyNVR作为一款功能强大的多品牌NVR管理工具/设备&#xff0c;凭借其灵活的部署方式和卓越的性能&#xff0c;正在引…

LSTM原理解读与实战

在RNN详解及其实战中&#xff0c;简单讨论了为什么需要RNN这类模型、RNN的具体思路、RNN的简单实现等问题。同时&#xff0c;在文章结尾部分我们提到了RNN存在的梯度消失问题&#xff0c;及之后的一个解决方案&#xff1a;LSTM。因此&#xff0c;本篇文章主要结构如下&#xff…

Springboot之登录模块探索(含Token,验证码,网络安全等知识)

简介 登录模块很简单&#xff0c;前端发送账号密码的表单&#xff0c;后端接收验证后即可~ 淦&#xff01;可是我想多了&#xff0c;于是有了以下几个问题&#xff08;里面还包含网络安全问题&#xff09;&#xff1a; 1.登录时的验证码 2.自动登录的实现 3.怎么维护前后端…

使用Element UI实现前端分页,前端搜索,及el-table表格跨页选择数据,切换分页保留分页数据,限制多选数量

文章目录 一、前端分页1、模板部分 (\<template>)2、数据部分 (data)3、计算属性 (computed)4、方法 (methods) 二、前端搜索1、模板部分 (\<template>)2、数据部分 (data)3、计算属性 (computed)4、方法 (methods) 三、跨页选择1、模板部分 (\<template>)2、…

VMware Workstation 17.6.1

概述 目前 VMware Workstation Pro 发布了最新版 v17.6.1&#xff1a; 本月11号官宣&#xff1a;针对所有人免费提供&#xff0c;包括商业、教育和个人用户。 使用说明 软件安装 获取安装包后&#xff0c;双击默认安装即可&#xff1a; 一路单击下一步按钮&#xff1a; 等待…