代码优化的案例
开发过程中,常常会出现for循环里面,存在多个SQL查询,根据for循环里面某个字段或者某2个字段去查询数据库,然后拿到结果,这个过程,如果for循环的集合比较大,同时如果查询的数据库的表有连表或者数据量较大,那么整个查询效率就会很低,我们可以将其进行优化,提高查询效率,话不多说直接上代码
原代码:
for(Order order : orderList) { ReportViewResp resp = new ReportViewResp(); BeanUtils.copyProperties(order, resp); createReportInfo(infoType,resp, order); result.add(resp); }
private void createReportInfo(InfoType infoType,ReportViewResp resp, Order order) { Lab lab = labCommand.getById(order.getLabId());if (Objects.nonNull(lab)) { resp.setLab(lab.getLabName()); } Sample sample = sampleCommand.getById(order.getSampleId());if (Objects.nonNull(sample)) { resp.setSample(sample.getSampleName()); }
...
}
如上图所示,createReportInfo方法里面有多个查询数据库的操作,这里是省略了,其实是有8个查询数据库,那我们都知道每次和数据库交互都会有连接,其实效率是比较低的,那鉴于此,我们将其尝试优化下
优化后:
InfoType infoType = handleDataMap(orderList); for(Order order : orderList) { ReportViewResp resp = new ReportViewResp(); BeanUtils.copyProperties(order, resp); createReportInfo(infoType,resp, order); result.add(resp); }
private InfoType handleDataMap(List<Order> orderList) { InfoType infoType = new InfoType(); // TestType testType = testTypeCommand.getById(order.getTestTypeId()); List<Long> testTypeIds = orderList.stream().map(Order::getTestTypeId).filter(Objects::nonNull).distinct().collect(Collectors.toList()); List<TestType> testTypeList = testTypeCommand.list(new LambdaQueryWrapper<TestType>().in(TestType::getId, testTypeIds)); Map<Long, TestType> testTypeMap = testTypeList.stream().collect(Collectors.toMap(TestType::getId, TestType -> TestType)); infoType.setTestTypeMap(testTypeMap); // Lab lab = labCommand.getById(order.getLabId()); List<Long> labIds = orderList.stream().map(Order::getLabId).filter(Objects::nonNull).distinct().collect(Collectors.toList()); List<Lab> labList = labCommand.list(new LambdaQueryWrapper<Lab>().in(Lab::getId, labIds)); Map<Long, Lab> labMap = labList.stream().collect(Collectors.toMap(Lab::getId, Lab -> Lab)); infoType.setLabMap(labMap); }
@Data public class InfoType { private Map<Long, TestType> testTypeMap = new HashMap<>(); private Map<Long, Lab> labMap = new HashMap<>(); }
private void createReportInfo(InfoType infoType,ReportViewResp resp, Order order) { Map<Long, Lab> labMap = infoType.getLabMap(); Lab lab = labMap.get(order.getLabId()); if (Objects.nonNull(lab)) { resp.setLab(lab.getLabName()); } Map<Long, Sample> sampleMap = infoType.getSampleMap(); Sample sample = sampleMap.get(order.getSampleId()); if (Objects.nonNull(sample)) { resp.setSample(sample.getSampleName()); } }
大致的思路就是先把结果集去查询数据库,然后转换为map或者list,再在下游拿到map,通过map.get(xx)的方式去获取到对应的数据,减少了for循环里面遍历查询数据。这里创建个对象是为了方便传递参数,如果只有1-2个,也可以直接传递map,如果存在多个,可以用创建个对象赋值属性的方式来使用。
下面再保存几个类似的案例:
@Data public class DfmeaInfoByType { private Map<Long, List<DfmeaTree>> treeMapByTreeId = new HashMap<>(); private Map<Long, FmeaKFa> fmeaKFaMap = new HashMap<>();
private Map<Long, DfmeaTree> dmfeaTreeByRelateFailIdsMap = new HashMap<>(); private List<FmeaStructuralTreeRules> fmeaStructuralTreeRulesList = new ArrayList<>();
treeMapByTreeId
#上游创建
LambdaQueryWrapper<DfmeaTree> treeLambdaQueryWrapper = new LambdaQueryWrapper<>(); treeLambdaQueryWrapper.in(!treeIds.isEmpty(),DfmeaTree::getAboutProdId, treeIds).or().apply(treeIds.isEmpty(),"1=0"); ; List<DfmeaTree> dfmeaTrees = this.baseMapper.selectList(treeLambdaQueryWrapper); Map<Long, List<DfmeaTree>> treeMapByTreeId = dfmeaTrees.stream().collect(Collectors.groupingBy(DfmeaTree::getAboutProdId)); infoByType.setTreeMapByTreeId(treeMapByTreeId);
#下游使用
Map<Long, List<DfmeaTree>> treeMapByTreeIdMap = infoMap.getTreeMapByTreeId();
List<DfmeaTree> dfmeaTrees = treeMapByTreeIdMap.getOrDefault(obj.getTreeId(),Collections.emptyList());
if(dfmeaTrees.size() > 0) {
treeNode.putExtra("hasChild", 1);
} else {
treeNode.putExtra("hasChild", 0);
}
fmeaKFaMap
#上游创建 LambdaQueryWrapper<FmeaKFa> wrapper = new LambdaQueryWrapper<>(); wrapper.in(FmeaKFa::getId,knowledgeIds).select(FmeaKFa::getId,FmeaKFa::getInvalidType); List<FmeaKFa> fmeaKFaList = this.fmeaKFaService.list(wrapper); Map<Long, FmeaKFa> fmeaKFaMap = fmeaKFaList.stream().collect(Collectors.toMap(FmeaKFa::getId, FmeaKFa -> FmeaKFa, (v1, v2) -> v1)); ##这里(v1, v2) -> v1),意思是如果存在多个,取第一个,而如果你确定只有一个,那不需要写这个
infoByType.setFmeaKFaMap(fmeaKFaMap);
#下游使用
Map<Long, FmeaKFa> fmeaKFaMap = infoMap.getFmeaKFaMap();
FmeaKFa fmeaKFa = fmeaKFaMap.get(obj.getKnowledgeId());
treeNode.putExtra("invalidType", fmeaKFa.getInvalidType());
treeNode.putExtra("text", fmeaTreeData.getDescName());
dmfeaTreeByRelateFailIdsMap
#上游创建 Set<Long> relateFailIds = fmeaTreeDataList.stream().map(FmeaTreeData::getRelateFailId).filter(ObjectUtil::isNotNull).collect(Collectors.toSet()); #这里可以将结果集去null去重 LambdaQueryWrapper<DfmeaTree> wrapper = new LambdaQueryWrapper<DfmeaTree>() .in(!relateFailIds.isEmpty(),DfmeaTree::getId, relateFailIds).or().apply(relateFailIds.isEmpty(),"1=0"); ##这一行代码的意思是,当relateFailIds不为空的时候,就用relateFailIds,当如果relateFailIds为空的时候,1=0为恒假条件,查询结果为空,就返回一个空的集合 wrapper.select(DfmeaTree::getId,DfmeaTree::getAboutProdId,DfmeaTree::getKnowledgeId); List<DfmeaTree> dfmeaTreeList = this.list(wrapper); Map<Long, DfmeaTree> dmfeaTreeByRelateFailIdsMap = dfmeaTreeList.stream().collect(Collectors.toMap(DfmeaTree::getId, DfmeaTree -> DfmeaTree)); ##这里因为通过id查询,有把握对象就只有一个,就不要v1、v2了,直接就写成这样 infoByType.setDmfeaTreeByRelateFailIdsMap(dmfeaTreeByRelateFailIdsMap); #下游使用 Map<Long, DfmeaTree> dmfeaTreeByRelateFailIdsMap = infoMap.getDmfeaTreeByRelateFailIdsMap(); DfmeaTree dfmeaTree = dmfeaTreeByRelateFailIdsMap.get(relateFailId);
fmeaStructuralTreeRulesList
#上游创建 List<FmeaStructuralTreeRules> fmeaStructuralTreeRulesList = rulesService.list( new LambdaQueryWrapper<FmeaStructuralTreeRules>().select(FmeaStructuralTreeRules::getId)); infoByType.setFmeaStructuralTreeRulesList(fmeaStructuralTreeRulesList); #下游使用 //List<FmeaStructuralTreeRules> list = rulesService.list(); List<FmeaStructuralTreeRules> list = infoMap.getFmeaStructuralTreeRulesList(); if (CollUtil.isNotEmpty(list)) { d = String.valueOf(list.get(0).getDfmeaD()); }
浙公网安备 33010602011771号