Java开发中如何避免在for循环中频繁访问数据库

Java开发中要避免在for循环中进行数据库的频繁访问,如果数据量大,那么for循环里就是频繁进行数据库操作,带来很大的IO开销,从而降低了应用的性能和响应的速度。下面通过举正反两个例子验证一下。

正例:

 // 从数据库中获取产品数据
    List<SpuInfoEntity> spuInfoEntities = spuInfoService.getBaseMapper().selectList(Wrappers.lambdaQuery(SpuInfoEntity.class)
            .select(SpuInfoEntity::getId, SpuInfoEntity::getBrandId));
    //将产品id收集到一个Set集合(防重复)
    Set<Long> spuIds = spuInfoEntities.stream().map(SpuInfoEntity::getId).collect(Collectors.toSet());
    //根据产品id查询该产品所有属性值
    Map<Long, List<ProductAttrValueEntity>> productAttrValuesMap = productAttrValueMapper.selectList(Wrappers.lambdaQuery(ProductAttrValueEntity.class)
            .in(ProductAttrValueEntity::getSpuId, spuIds))
            .stream()
            .collect(Collectors.groupingBy(ProductAttrValueEntity::getSpuId));
    //根据产品id查询该商品信息
    Map<Long, SkuInfoEntity> skuInfoMap = skuInfoMapper.selectList(Wrappers.lambdaQuery(SkuInfoEntity.class)
            .in(SkuInfoEntity::getSpuId, spuIds))
            .stream()
            .collect(Collectors.toMap(SkuInfoEntity::getSpuId, Function.identity()));
    //根据产品id查询该品牌信息
    Map<Long, Brand> brandMap = brandMapper.selectBatchIds(spuInfoEntities.stream().map(SpuInfoEntity::getBrandId).collect(Collectors.toSet()))
            .stream()
            .collect(Collectors.toMap(Brand::getBrandId, Function.identity()));
    //根据产品id查询产品图片信息
    Map<Long, List<SpuImagesEntity>> spuImagesMap = spuImagesMapper.selectList(Wrappers.lambdaQuery(SpuImagesEntity.class)
                    .in(SpuImagesEntity::getSpuId, spuIds))
            .stream()
            .collect(Collectors.groupingBy(SpuImagesEntity::getSpuId));

    // 构建 SpuInfoVo 列表
    List<SpuInfoVo> spuInfoVoList = spuInfoEntities.stream()
    //使用过滤器保留符合条件的产品,将产品中不符合条件的剔除掉
    .filter(spuInfo -> {
        List<ProductAttrValueEntity> attrValues = productAttrValuesMap.getOrDefault(spuInfo.getId(), Collections.emptyList());
        boolean hasThresholds = attrValues.stream().anyMatch(attrValue -> "内存大小".equals(attrValue.getAttrName()));
        boolean hasChargeStyle = attrValues.stream().anyMatch(attrValue -> "颜色".equals(attrValue.getAttrName()));
        return hasThresholds && hasChargeStyle;
    })
    .map(spuInfo -> {
        SpuInfoVo spuInfoVo = new SpuInfoVo();
        BeanUtils.copyProperties(spuInfo, spuInfoVo);
        List<ProductAttrValueEntity> attrValues = productAttrValuesMap.getOrDefault(spuInfo.getId(), Collections.emptyList());
        attrValues.forEach(attrValue -> {
            switch (attrValue.getAttrName()) {
                case "内存大小":
                    String attrValue1 = attrValue.getAttrValue();
                    List<String>attrValueList=new ArrayList<>();
                    if(attrValue1!=null&&attrValue1.contains(",")){
                        attrValueList.addAll(Arrays.asList(attrValue1.split(",")));
                    }else {
                        attrValueList.add(attrValue1);
                    }
                    spuInfoVo.setThresholds(attrValueList);
                    break;
                case "颜色":

                    spuInfoVo.setChargeStyle(attrValue.getAttrValue());
                    break;
            }
        });
        //从map取出对应产品id的商品信息
        SkuInfoEntity skuInfo = skuInfoMap.get(spuInfo.getId());
        spuInfoVo.setPrice(skuInfo == null ? BigDecimal.ZERO : skuInfo.getPrice());
         //从map取出对应产品id的品牌信息
        Brand brand = brandMap.get(spuInfo.getBrandId());
        spuInfoVo.setBrandName(brand == null ? "" : brand.getName());
        List<SpuImagesEntity> images = spuImagesMap.getOrDefault(spuInfo.getId(), Collections.emptyList());
        if (!images.isEmpty()) {
            spuInfoVo.setImgUrl(images.get(0).getImgUrl());
        }

        return spuInfoVo;
    }).collect(Collectors.toList());

 经测试,共耗时1956毫秒

反例:

       LambdaQueryWrapper<SpuInfoEntity>queryWrapper=Wrappers.lambdaQuery();
        queryWrapper.select(SpuInfoEntity::getId,SpuInfoEntity::getBrandId);
        List<SpuInfoEntity> spuInfoEntities = spuInfoService.getBaseMapper().selectList(queryWrapper);
        List<SpuInfoVo>spuInfoVoList =new ArrayList<>();
        for (SpuInfoEntity spuInfo : spuInfoEntities) {
            SpuInfoVo spuInfoVo=new SpuInfoVo();
            BeanUtils.copyProperties(spuInfo,spuInfoVo);
            LambdaQueryWrapper<ProductAttrValueEntity>productAttrValueWrapper=Wrappers.lambdaQuery();
            productAttrValueWrapper.select(ProductAttrValueEntity::getSpuId,ProductAttrValueEntity::getAttrName,ProductAttrValueEntity::getAttrValue);
            productAttrValueWrapper.eq(ProductAttrValueEntity::getAttrName,"颜色");
            productAttrValueWrapper.eq(ProductAttrValueEntity::getSpuId,spuInfo.getId());
            ProductAttrValueEntity attrValue = productAttrValueMapper.selectOne(productAttrValueWrapper);
            if(attrValue==null){
                continue;
            }
            String attrValue1 = attrValue.getAttrValue();
            List<String>attrValues=new ArrayList<>();
            if(attrValue1!=null&&attrValue1.contains(",")){
                attrValues.addAll(Arrays.asList(attrValue1.split(",")));
            }else {
                attrValues.add(attrValue1);
            }
            spuInfoVo.setThresholds(attrValues);
            LambdaQueryWrapper<ProductAttrValueEntity>productAttrValueWrapper2=Wrappers.lambdaQuery();
            productAttrValueWrapper2.select(ProductAttrValueEntity::getSpuId,ProductAttrValueEntity::getAttrName,ProductAttrValueEntity::getAttrValue);
            productAttrValueWrapper2.eq(ProductAttrValueEntity::getAttrName,"内存大小");
            productAttrValueWrapper2.eq(ProductAttrValueEntity::getSpuId,spuInfo.getId());
            ProductAttrValueEntity attrValue2 = productAttrValueMapper.selectOne(productAttrValueWrapper2);
            if(attrValue2==null){
                continue;
            }
            spuInfoVo.setChargeStyle(attrValue2.getAttrValue());
        
  
            SkuInfoEntity skuInfoEntity = skuInfoMapper.selectOne(new LambdaQueryWrapper<SkuInfoEntity>().select(SkuInfoEntity::getSkuId,
                    SkuInfoEntity::getSpuId, SkuInfoEntity::getPrice).eq(SkuInfoEntity::getSpuId,spuInfo.getId()).orderByAsc(SkuInfoEntity::getSkuId).last("LIMIT 1"));
            spuInfoVo.setPrice(skuInfoEntity==null?BigDecimal.ZERO:skuInfoEntity.getPrice());
            Brand brand = brandMapper.selectById(spuInfo.getBrandId());
            spuInfoVo.setBrandName(brand==null?"":brand.getName());
            List<SpuImagesEntity> spuImagesEntities = spuImagesMapper.selectList(new LambdaQueryWrapper<SpuImagesEntity>().eq(SpuImagesEntity::getSpuId, spuInfo.getId()));
            spuInfoVo.setImgUrl(spuImagesEntities.get(0).getImgUrl());
            spuInfoVoList.add(spuInfoVo);
        }

反例在for循环中访问数据库进行查询操作,经测试,共耗时124546毫秒,即2分多钟,这个执行时间堪称灾难级。

通过上方正反两个例子说明,在实际开发中,在避免在for循环里进行大量的数据库访问,正确的方式是进行一次查询,将id收集成一个集合,然后再根据id逐个查询,并保存在map集合中,id作为map集合的key,取值时根据id这个key,取出对应的value,如何使用请参考上方的正例。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值