小鹏汽车智慧材料数据库系统项目总成数据同步
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_idfrom (SELECT bpa.master_part_id, bpa.sub_part_id FROM bm_part_assembly bpa WHERE bpa.bom_type = 'PART') aINNER 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 bpaleft join bm_part_assembly_ext bpae on bpae.bm_part_assembly_ext_id = bpa.part_assembly_ext_idinner 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 车型的 23821and 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 车型的 23821and 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">selectbpa.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 inheritedRemodeledModelsfrom bm_part_assembly bpaleft join bm_part_assembly_ext bpae on bpae.bm_part_assembly_ext_id = bpa.part_assembly_ext_idinner join bm_md_material bmm on bmm.md_material_id = bpa.sub_part_idwhere (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 > #{lastSyncUpdateDate}</if><if test="masterPartId!='' and masterPartId!=null">and bpa.master_part_id = #{masterPartId}</if>ORDER BY bpa.update_date DESCLIMIT #{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 materielEnNamefrom bm_md_material bmmwhere bmm.md_material_id in (SELECT bpa.master_part_id from(SELECT bpa.master_part_id, bpa.sub_part_id FROM bm_part_assembly bpaWHERE bpa.bom_type = 'PART') aINNER 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 organizationIdfrom bm_acct_user bau where user_id = #{employeeId};</select><!-- 责任部门 --><select id="bomResponsibleDepartment" resultType="com.ruiyada.whole.domain.vo.BomAssemblyVo">selectbao.id as orgId, bao.org_name as bomResponsibleDepartment, bao.org_name_en as orgNameEnfrom bm_acct_organization baowhere id = #{organizationId}</select><!--生效ECN编号--><select id="selectEcnNumberEffect" resultType="string">select bmc.change_code AS ecnNumberEffectfrom 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 materielCodefrom bm_md_material bmmwhere md_material_id in<foreach item="item" index="index" collection="materialIds" open="(" separator="," close=")">#{item}</foreach></select><!-- 统计车型下的总成总数 --><select id="assentlyCount" resultType="java.lang.Integer">selectcount(1)from bm_part_assembly bpaleft join bm_part_assembly_ext bpae on bpae.bm_part_assembly_ext_id = bpa.part_assembly_ext_idinner join bm_md_material bmm on bmm.md_material_id = bpa.sub_part_idwhere (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 {@Autowiredprivate BomAssemblyMaterialPartsMapper bomAssemblyMaterialPartsMapper;@Autowiredprivate BomCategoryService bomCategoryService;
@Overridepublic 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设为0List<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) {// 不存在,则就生成idid = 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_id3、根据拿到每个车型的md_material_id 查询 bm_part_assembly表的master_part_id,就得到了得到sub_part_id4、得到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 bmmwhere 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 和 materialNumSet<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 bmmwhere 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;}@Overridepublic 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 {@Autowiredprivate BomAssemblyMaterialPartsService bomAssemblyMaterialPartsService;@Resourceprivate 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);}}
相关文章:
小鹏汽车智慧材料数据库系统项目总成数据同步
1、定时任务处理 2、提供了接口 小鹏方面提供的推送的数据表结构: 这几个表总数为100多万,经过条件筛选过滤后大概2万多条数据 小鹏的人给的示例图: 界面: SQL: -- 查询车型 select bmm.md_material_id, bmm.material_num, bm…...
1、HCIP之RSTP协议与STP相关安全配置
目录 RSTP—快速生成树协议 STP STP的缺点: STP的选举(Listening状态中): RSTP P/A(提议/同意)机制 同步机制: 边缘端口的配置: RSTP的端口角色划分: ensp模拟…...
Linux云服务器docker使用教程
诸神缄默不语-个人CSDN博文目录 我用的是腾讯云服务器,操作系统是OpenCloudOS 9,基本上可以当特色版CentOS用。 docker安装跟各个系统关系太大了,我就不写了。OpenCloudOS 9安装docker见这篇博文:腾讯云服务器使用教程 文章目录 …...
如何从android的webview 取得页面上的数据
要从Android的WebView中获取页面上的数据,通常有几种常见的方法: JavaScript Interface:通过JavaScript和Android Interface进行通信。这种方法允许你在JavaScript中调用Android的方法,反之亦然。 Evaluate JavaScriptÿ…...
VTK知识学习(12)- 读取PNG图像
1、代码 private void ShowPngImage(){vtkPNGReader pngReader vtkPNGReader.New();pngReader.SetFileName("D:\\图像\\boxes\\cardboard_boxes_01.png");pngReader.Update();vtkImageActor imageActor vtkImageActor.New();imageActor.SetInputData(pngReader.Get…...
Springboot项目搭建(3)-更改用户信息与文件上传
1.概要 前一章节完成了用户信息的注册、登录、详细信息查询,以及线程池与拦截器技术。 这一章完善了用户信息更新/更改功能,包括昵称、邮箱、头像、密码等... 而后接触到了本地上传和云上传,其二者区别: 选择本地上传还是云上…...
Docker1:认识docker、在Linux中安装docker
欢迎来到“雪碧聊技术”CSDN博客! 在这里,您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者,还是具有一定经验的开发者,相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导,我将…...
python成绩分级 2024年6月python二级真题 青少年编程电子学会编程等级考试python二级真题解析
目录 python成绩分级 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序代码 四、程序说明 五、运行结果 六、考点分析 七、 推荐资料 1、蓝桥杯比赛 2、考级资料 3、其它资料 python成绩分级 2024年6月 python编程等级考试二级编程题 一、题目要求 …...
android 如何获取当前 Activity 的类名和包名
其一:getClass().getSimpleName() public static String getTopActivity(Context context){ ActivityManager am (ActivityManager) context.getSystemService(context.ACTIVITY_SERVICE); ComponentName cn am.getRunningTasks(1).get(0).topAct…...
Spring Boot 项目 myblog 整理
myblog 项目是一个典型的 Spring Boot 项目,主要包括用户注册、登录、文章管理(创建、查询、更新、删除)等功能。 1. 项目结构与依赖设置 项目初始化与依赖 使用 Spring Initializr 创建项目。引入必要的依赖包: Spring Boot W…...
uniapp 城市选择插件
uniapp城市选择插件 如上图 地址 完整demo <template><view><city-selectcityClick"cityClick":formatName"formatName":activeCity"activeCity":hotCity"hotCity":obtainCitys"obtainCitys":isSearch&quo…...
测试工程师如何在面试中脱颖而出
目录 1.平时工作中是怎么去测的? 2.B/S架构和C/S架构区别 3.B/S架构的系统从哪些点去测? 4.你为什么能够做测试这一行?(根据个人情况分析理解) 5.你认为测试的目的是什么? 6.软件测试的流程ÿ…...
Mesh路由组网
Mesh无线网格网络,多跳(multi-hop)网络,为解决全屋覆盖信号,一般用于家庭网络和小型企业 原理 网关路由器(主路由,连接光猫),Mesh路由器(子路由,…...
LeetCode131:分割回文串
题目链接:131. 分割回文串 - 力扣(LeetCode) 代码如下: class Solution { private:vector<vector<string>> result;vector<string> path; // 放已经回文的子串void backtracking (const string& s, int s…...
详细解析 devmem 命令:在 Linux 系统中直接访问内存的利器
目录 什么是 devmem?为什么需要 devmem?devmem 命令的基本语法devmem 在硬件调试中的应用安全性与风险devmem 的常见应用示例结论 在嵌入式系统开发和硬件调试中,开发者经常需要直接与硬件打交道,访问和修改内存中某些特定区域的内…...
[Docker-显示所有容器IP] 显示docker-compose.yml中所有容器IP的方法
本文由Markdown语法编辑器编辑完成。 1. 需求背景: 最近在启动一个服务时,突然发现它的一个接口,被另一个服务ip频繁的请求。 按理说,之前设置的是,每隔1分钟请求一次接口。但从日志来看,则是1秒钟请求一次ÿ…...
【前端知识】nodejs项目配置package.json深入解读
package.json详细解读 文件解读一、文件结构二、字段详解三、使用场景四、注意事项 组件版本匹配规则 文件解读 package.json 文件是 Node.js 项目中的一个核心配置文件,它位于项目的根目录下,并包含项目的基本信息、依赖关系、脚本、版本等内容。以下是…...
XGBOOST算法Python实现(保姆级)
摘要 XGBoost算法(eXtreme Gradient Boosting)在目前的Kaggle、数学建模和大数据应用等竞赛中非常流行。本文将会从XGBOOST算法原理、Python实现、敏感性分析和实际应用进行详细说明。 目录 0 绪论 一、材料准备 二、算法原理 三、算法Python实现 3…...
JDK、MAVEN与IDEA的安装与配置
1.认识JDK、MAVEN与IDEA JDK 提供了编译和运行Java程序的基本环境。Maven 帮助管理项目的构建和依赖。IDEA 提供了一个强大的开发环境,使得编写、调试和运行Java程序更加高效。 2. 安装与环境配置 2.1 官网地址 选择你需要的版本下载: MAVEN下载传送…...
输出比较简介
输出比较简介 主要是用来输出PWM波形,这个波形是驱动电机的(智能车和机器人等)必要条件 OC(Output Compare)输出比较,还有IC,全称是Input Capture,意为输入捕获,还有CC…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
高危文件识别的常用算法:原理、应用与企业场景
高危文件识别的常用算法:原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件,如包含恶意代码、敏感数据或欺诈内容的文档,在企业协同办公环境中(如Teams、Google Workspace)尤为重要。结合大模型技术&…...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
rnn判断string中第一次出现a的下标
# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...
Pinocchio 库详解及其在足式机器人上的应用
Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...
计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...
