小鹏汽车智慧材料数据库系统项目总成数据同步
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…...
风尚云网前端学习:一个简易前端新手友好的HTML5页面布局与样式设计
风尚云网前端学习:一个简易前端新手友好的HTML5页面布局与样式设计 简介 在前端开发的世界里,HTML5和CSS3是构建现代网页的基石。本文将通过一个简单的HTML5页面模板,展示如何使用HTML5的结构化元素和CSS3的样式特性,来创建一个…...
论文阅读:A fast, scalable and versatile tool for analysis of single-cell omics data
Zhang, K., Zemke, N.R., Armand, E.J. et al. A fast, scalable and versatile tool for analysis of single-cell omics data. Nat Methods 21, 217–227 (2024). 论文地址:https://doi.org/10.1038/s41592-023-02139-9 代码地址:https://github.com…...
【从零开始的LeetCode-算法】43. 网络延迟时间
有 n 个网络节点,标记为 1 到 n。 给你一个列表 times,表示信号经过 有向 边的传递时间。 times[i] (ui, vi, wi),其中 ui 是源节点,vi 是目标节点, wi 是一个信号从源节点传递到目标节点的时间。 现在,…...
一文理解 Python 编程语言中的 .strip() 方法
🍉 CSDN 叶庭云:https://yetingyun.blog.csdn.net/ Python 中的 strip() 方法:初学者友好指南 在 Python 中,strip() 是一个极为实用的字符串方法,主要用于移除字符串首尾的特定字符。默认情况下,它会清除…...
solr 远程命令执行 (CVE-2019-17558)
漏洞描述 Apache Velocity是一个基于Java的模板引擎,它提供了一个模板语言去引用由Java代码定义的对象。Velocity是Apache基金会旗下的一个开源软件项目,旨在确保Web应用程序在表示层和业务逻辑层之间的隔离(即MVC设计模式)。 Apa…...
【cocos creator】下拉框
https://download.csdn.net/download/K86338236/90038176 const { ccclass, property } cc._decorator;type DropDownOptionData {optionString?: string,optionSf?: cc.SpriteFrame } type DropDownItemData {label: cc.Label,sprite: cc.Sprite,toggle: cc.Toggle }cccl…...
从 Llama 1 到 3.1:Llama 模型架构演进详解
编者按: 面对 Llama 模型家族的持续更新,您是否想要了解它们之间的关键区别和实际性能表现?本文将探讨 Llama 系列模型的架构演变,梳理了 Llama 模型从 1.0 到 3.1 的完整演进历程,深入剖析了每个版本的技术创新&#…...
电话机器人的最佳应用
电话机器人的最佳应用 作者:开源呼叫中心系统 FreeIPCC,Github地址:https://github.com/lihaiya/freeipcc 电话机器人在多个领域中都展现出了其独特的优势和广泛的应用前景。以下是对电话机器人最佳应用的详细归纳: 一、销售与营…...
[面试]-golang基础面试题总结
文章目录 panic 和 recover**注意事项**使用 pprof、trace 和 race 进行性能调试。**Go Module**:Go中new和make的区别 Channel什么是 Channel 的方向性?如何对 Channel 进行方向限制?Channel 的缓冲区大小对于 Channel 和 Goroutine 的通信有…...
Fakelocation Server服务器/专业版 ubuntu
前言:需要Ubuntu系统 Fakelocation开源文件系统需求 Ubuntu | Fakelocation | 任务一 任务一 更新Ubuntu(安装下载不再赘述) sudo -i # 提权 sudo apt update # 更新软件包列表 sudo apt upgrade # 升级已安装的软…...
Node.js的http模块:创建HTTP服务器、客户端示例
新书速览|Vue.jsNode.js全栈开发实战-CSDN博客 《Vue.jsNode.js全栈开发实战(第2版)(Web前端技术丛书)》(王金柱)【摘要 书评 试读】- 京东图书 (jd.com) 要使用http模块,只需要在文件中通过require(http)引入即可。…...
Jackson 对象与json数据互转工具类JacksonUtil
下面是一个基于 Jackson 的工具类 JacksonUtil,用于在 Java 项目中实现对象与 JSON 数据之间的互相转换。该工具类具有简洁、易用、通用的特点。 package com.fy.common.util;import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core…...
【ArcGISPro】根据yaml构建原始Pro的conda环境
使用场景 我们不小心把原始arcgispro-py3的conda环境破坏了,我们就可以使用以下方法进行修复 查找文件 在arcgis目录下找到yaml文件 如果没找到请复制以下内容到新的yaml文件 channels: - esri - defaults dependencies: - anyio=4.2.0=py311haa95532_0 - appdirs=1.4.4=p…...
对撞双指针(七)三数之和
15. 三数之和 给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k ,同时还满足 nums[i] nums[j] nums[k] 0 。请你返回所有和为 0 且不重复的三元组。 注意:答案中不可以包含重复的三元组…...
反向代理服务器的用途
代理服务器在网络中扮演着重要的角色,它们可以优化流量、保护服务器以及提高安全性。在代理服务器中,反向代理服务器是一种特殊类型,常用于Web服务器前,它具备多种功能,能够确保网络流量的顺畅传输。那么,让…...
一些好的AI技术学习平台和资料(动态更新)
1. 大模型 1.1 提示词(Prompt) 目前,大模型技术已经深入到工作生活的方方面面,各技术大厂的大模型也层出不穷,从开始的OpenAI一家独大,到当今世界的“百模大战”。从一些日常使用的角度来说,模…...
wireshark抓包分析HTTP协议,HTTP协议执行流程,
「作者主页」:士别三日wyx 「作者简介」:CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」:对网络安全感兴趣的小伙伴可以关注专栏《网络安全入门到精通》 使用WireShark工具抓取「HTTP协议」的数据包&#…...
路由缓存后跳转到新路由时,上一路由中的tip信息框不销毁问题解决
上一路由tip信息框不销毁问题解决 路由缓存篇问题描述及截图解决思路关键代码 路由缓存篇 传送门 问题描述及截图 路由缓存后跳转新路由时,上一个路由的tip信息框没销毁。 解决思路 在全局路由守卫中获取DOM元素,通过css去控制 关键代码 修改文…...
【Angular】async详解
在 Angular 中,async 关键字用于定义异步函数,通常与 await 一起使用来处理 Promise。这使得异步代码看起来更像同步代码,从而更容易理解和维护。 基本用法 定义异步函数:使用 async 关键字。等待 Promise 解析:使用…...
springboot/ssm综合小区管理系统Java社区物业停车缴费系统web物业源码
springboot/ssm综合小区管理系统Java社区物业停车缴费系统web物业源码 基于springboot(可改ssm)htmlvue项目 开发语言:Java 框架:springboot/可改ssm vue JDK版本:JDK1.8(或11) 服务器:tomcat 数据库&…...
【51单片机】程序实验56.独立按键-矩阵按键
主要参考学习资料:B站【普中官方】51单片机手把手教学视频 前置知识:C语言 单片机套装:普中STC51单片机开发板A4标准版套餐7 码字不易,求点赞收藏加关注(•ω•̥) 有问题欢迎评论区讨论~ 目录 独立按键按键介绍实验5 独立按键 矩…...
SAP 零售方案 CAR 系统的介绍与研究
前言 当今时代,零售业务是充满活力和活力的业务领域之一。每天,由于销售运营和客户行为,它都会生成大量数据。因此,公司迫切需要管理数据并从中检索见解。它将帮助公司朝着正确的方向发展他们的业务。 这就是为什么公司用来处理…...
2024 APMCM亚太数学建模C题 - 宠物行业及相关产业的发展分析和策略 完整参考论文(2)
5.2 问题一模型的建立与求解 5.2.1 分析发展情况 为了更好地理解数据的变化趋势,利用matlab通过六个子图对宠物行业中的关键变量进行了可视化展示。 图 1. 宠物数量变化展示了 猫数量、狗数量 和 总宠物数量 在 2019-2023 年间的变化趋势。结果显示:猫的数量呈逐年上升的趋…...
嵌入式的C/C++:深入理解 static、const 与 volatile 的用法与特点
目录 一、static 1、static 修饰局部变量 2、 static 修饰全局变量 3、static 修饰函数 4、static 修饰类成员 5、小结 二、const 1、const 修饰普通变量 2、const 修饰指针 3、const 修饰函数参数 4. const 修饰函数返回值 5. const 修饰类成员 6. const 与 #defi…...
【数据库设计】软件系统需要同时设计注册日志表和登录日志表吗
是的,通常情况下,注册日志表和登录日志表是分别设计的,分别记录不同类型的事件信息。 注册日志表 记录用户的注册信息、注册方式以及是否成功等内容。登录日志表 记录用户每次登录的时间、IP 地址、设备信息、登录状态等内容。 尽管这两者看…...
vim 一次注释多行 的几种方法
在 Vim 中一次注释多行是一个常见操作。可以使用以下方法根据你的具体需求选择合适的方式: 方法 1:手动插入注释符 进入正常模式: 按 Esc 确保进入正常模式。 选择需要注释的多行: 移动到第一行,按下 Ctrlv 进入可视块…...
手机无法连接服务器1302什么意思?
你有没有遇到过手机无法连接服务器,屏幕上显示“1302”这样的错误代码?尤其是在急需使用手机进行工作或联系朋友时,突然出现的连接问题无疑会带来不少麻烦。那么,什么是1302错误,它又意味着什么呢? 1302错…...
Git(一)基本使用
目录 一、使用git -v 查看安装git版本 二、使用mkdir 创建一个文件,并使用 git init 在该目录下创建一个本地仓库, 三、通过git clone命令接入线上仓库 四、使用git status查看仓库状态信息 五、利用echo写入一个文件 并使用cat进行查看 【Linux】e…...
sklearn中常用数据集简介
scikit-learn库中提供了包括分类、回归、聚类、降维等多种机器学习任务所需的常用数据集,方便进行实验和研究,它们主要被封装在sklearn.datasets中,本文对其中一些常用的数据集进行简单的介绍。 1.Iris(鸢尾花)数据集…...
LRU缓存
什么是LRU缓存? LRU(Least Recently Used)是最近最少使用算法,是操作系统中用于分页置换的算法,如果要向内存中添加分页,并且内存分页已满的情况下,就选出最近一段时间最不常用的分页进行置换(…...
.net6 使用 FreeSpire.XLS 实现 excel 转 pdf - docker 部署
FreeSpire.XLS && Aspose.Cells包都可以实现。实现过程中发现如下问题: 本地测试通过, docker部署服务器后报错: The type initializer for Spire.Xls.Core.Spreadsheet.XlsPageSetupBase threw an exception. 由于缺少依赖…...
HttpServletRequest req和前端的关系,req.getParameter详细解释,req.getParameter和前端的关系
HttpServletRequest 对象在后端和前端之间起到了桥梁的作用,它包含了来自客户端的所有请求信息。通过 HttpServletRequest 对象,后端可以获取前端发送的请求参数、请求头、请求方法等信息,并根据这些信息进行相应的处理。以下是对 HttpServle…...
[Python3] Sanic 框架构建高并发的 Web 服务
在 Python3 中使用 Sanic 框架来构建高并发的 Web 服务时,Sanic 因其异步和基于事件驱动的架构能够很好地处理高并发请求。下面是如何使用 Sanic 的一些要点和示例代码。 1. 安装 Sanic 首先确保你安装了 Sanic,可以通过以下命令安装: pip…...
5.5 W5500 TCP服务端与客户端
文章目录 1、TCP介绍2、W5500简介2.1 关键函数socketlistensendgetSn_RX_RSRrecv自动心跳包检测getSn_SR 1、TCP介绍 TCP 服务端: 创建套接字[socket]:服务器首先创建一个套接字,这是网络通信的端点。绑定套接字[bind]:服务器将…...
【Flutter】搭建Flutter开发环境,安卓开发
Flutter是谷歌开源的一个跨平台开发的框架,方便好用,这里以Windows 上构建 Flutter Android 应用为例,记录下我搭建环境时碰到的一些问题以及解决。 第一步:参考官网:开发 Android 应用 | Flutter 中文文档 - Flutter …...
【机器学习】——朴素贝叶斯模型
💻博主现有专栏: C51单片机(STC89C516),c语言,c,离散数学,算法设计与分析,数据结构,Python,Java基础,MySQL,linux…...
k8s rainbond centos7/win10 -20241124
参考 https://www.rainbond.com/ 国内一站式云原生平台 对centos7环境支持不太行 [lighthouseVM-16-5-centos ~]$ curl -o install.sh https://get.rainbond.com && bash ./install.sh 2024-11-24 09:56:57 ERROR: Ops! Docker daemon is not running. Start docke…...
ctfshow单身杯2024wp
文章目录 ctfshow单身杯2024wp签到好玩的PHPezzz_sstiez_inject ctfshow单身杯2024wp 签到好玩的PHP 考点:序列化反序列化 <?phperror_reporting(0);highlight_file(__FILE__);class ctfshow {private $d ;private $s ;private $b ;private $ctf ;public …...
深入解密 K 均值聚类:从理论基础到 Python 实践
1. 引言 在机器学习领域,聚类是一种无监督学习的技术,用于将数据集分组成若干个类别,使得同组数据之间具有更高的相似性。这种技术在各个领域都有广泛的应用,比如客户细分、图像压缩和市场分析等。聚类的目标是使得同类样本之间的…...
【代码pycharm】动手学深度学习v2-08 线性回归 + 基础优化算法
课程链接 线性回归的从零开始实现 import random import torch from d2l import torch as d2l# 人造数据集 def synthetic_data(w,b,num_examples):Xtorch.normal(0,1,(num_examples,len(w)))ytorch.matmul(X,w)bytorch.normal(0,0.01,y.shape) # 加入噪声return X,y.reshape…...
Python绘制太极八卦
文章目录 系列目录写在前面技术需求1. 图形绘制库的支持2. 图形绘制功能3. 参数化设计4. 绘制控制5. 数据处理6. 用户界面 完整代码代码分析1. rset() 函数2. offset() 函数3. taiji() 函数4. bagua() 函数5. 绘制过程6. 技术亮点 写在后面 系列目录 序号直达链接爱心系列1Pyth…...
sklearn学习
介绍:scaler:换算的意思 1. 归一化MinMaxScaler() 归一化的意思是将一堆数,如果比较离散,为了让数据更适合模型训练,将离散的数据压缩到0到1之间,以方便模型更高效优质的学习,而对数据的预处理…...
# [Unity] 【游戏开发】Unity开发基础2-Unity脚本编程基础详解
Unity脚本编程是创建互动式游戏体验的核心技能之一。本文将详细讲解Unity脚本编程的基础知识,包括变量和数据类型、程序逻辑、方法等方面,并通过实例展示如何使用这些基本知识完成简单功能的实现。 1. 新建Unity脚本的基本结构 当在Unity中创建一个脚本时,Unity会生成如下基…...
【强化学习的数学原理】第02课-贝尔曼公式-笔记
学习资料:bilibili 西湖大学赵世钰老师的【强化学习的数学原理】课程。链接:强化学习的数学原理 西湖大学 赵世钰 文章目录 一、为什么return重要?如何计算return?二、state value的定义三、Bellman公式的详细推导四、公式向量形式…...
C语言-数学基础问题
一.奇数、偶数问题 1.从键盘上输入一个整数,判断并输出它是奇数还是偶数。 //从键盘上输入一个整数,判断并输出它是奇数还是偶数。 main() {int i;printf("输入一个整数:\n");scanf("%d",&i);if(i%20)printf("它是偶数\n…...
2024算法基础公选课练习四(综合2)
一、前言 最后几个题确实有难度,这次有两题没整出来 二、题目总览 三、具体题目 3.1 问题 A: 水题系列1-B(班级排位) 思路 最暴力的思路是写线段树,然后暴力枚举两个端点,总体时间复杂度为O(n^2*logn)最坏会到1e9的数量级,可能…...
小程序-使用 iconfont 图标库报错:Failed to load font
官方默认可以忽略此错误,在清除缓存后首次刷新会显示此错误,重新渲染错误消失 解决方法: 在 iconfont 图标库选择项目设置 选中 Base64 保存,重新点击链接 -> 复制代码到项目中 操作步骤:...
鲸鱼机器人和乐高机器人的比较
鲸鱼机器人和乐高机器人各有其独特的优势和特点,家长在选择时可以根据孩子的年龄、兴趣、经济能力等因素进行综合考虑,选择最适合孩子的教育机器人产品。 优势 鲸鱼机器人 1)价格亲民:鲸鱼机器人的产品价格相对乐高更为亲民&…...
解决单元测试时找不到类名
场景: springboot单元测试mockito对mapper进行mock时: tk.mybatis.mapper.mapperexception: 无法获取实体类 XX.xx 对应的表名 分析: 使用了一个方法:Example examplenew Example(User.class); 进入源码后发现Entityhelper没…...