jFreeChart的gravatar头像
jFreeChart 2015-09-19 20:46:15

spring MVC+myBatis批量上传大量excel数据插入mysql中很慢该怎么解决?

该业务层方法,调用了很多 dao层的方法                 分层思想

批量上传很多excl数据到数据库里, 业务层需要进行比较多的逻辑判断,(真实插入数据库里的数据,还需要和原数据库里的数据做一些业务判断),最后才插入数据数据库中!

我现在数据量大了, 很慢, 请问怎么解决,

//目前的代码,就是 for 循环 里面多次进往数据库进行检索,得出最后要插入的数据,再进行保存(用的是springMVC+myBatis+mysql  || 我处理这些问题是在  业务层)

//请问如何解决


        BizResponse<List<BizProdListingInfoForUpload>> res = new BizResponse<List<BizProdListingInfoForUpload>>();
        if (list == null || list.size() == 0)
        {
            logger.error("uploadForBatch : list null");
            return null;
        }
        DbResponse<AccountInfo> dbRes = accDbService.getById(new Long(accountId));
        AccountInfo acc = dbRes.getData();
        if (acc == null)
        {
            logger.error("uploadForBatch : accDbService.getById null. id=" + accountId);
            return null;
        }

        Integer parentId = null;
        if (acc.getParentId() != null)
        {
            parentId = acc.getParentId().intValue();
        }
        DbResponse<ChannelCategory> channelRes = chCategoryDbService.getChCategoryByChIdAndCategoryId(new Long(
                channelId), new Long(categoryId));
        ChannelCategory chCategory = channelRes.getData();
        if (chCategory == null)
        {
            logger.error("uploadForBatch : chCategoryDbService.getChCategoryByChIdAndCategoryId null. channelId="
                    + channelId + " categoryId=" + categoryId);
            return null;
        }

        List<BizProdListingInfoForUpload> bizList = new ArrayList<BizProdListingInfoForUpload>();
        outer: for (int i = 0; i < list.size(); i++)
        {
            BizProdListingInfoForUpload bizRes = null;
            Reportable obj = list.get(i);
            if (obj instanceof BaseCategory)
            {
                BaseCategory cate = (BaseCategory) obj;

                if (StringUtils.isEmpty(cate.getTitle()) || StringUtils.isEmpty(cate.getDescription())
                        || StringUtils.isEmpty(cate.getKeywords()) || cate.getPrice() == null)
                {
                    logger.error("uploadForBatch : there are some required for null");
                    bizRes = convertFailedBizProdListingInfoForUpload(cate);
                    bizList.add(bizRes);
                    continue;
                }

                String attributes = convertPojoToStringArray(cate);
                if (attributes == null)
                {
                    logger.error("uploadForBatch : convertPojoToString failed");
                    bizRes = convertFailedBizProdListingInfoForUpload(cate);
                    bizList.add(bizRes);
                    continue;
                }

                if (cate.getSku() == null)
                {
                    logger.error("uploadForBatch : get sku failed. for channelSku=" + cate.getChannelSku());
                    bizRes = convertFailedBizProdListingInfoForUpload(cate);
                    bizList.add(bizRes);
                    continue;
                }
                if (cate.getProductCount() == null)
                {
                    logger.error("uploadForBatch : get sku failed. for ProductCount=" + cate.getProductCount());
                    bizRes = convertFailedBizProdListingInfoForUpload(cate);
                    bizList.add(bizRes);
                    continue;
                }

                String sku1 = cate.getSku1();
                // String productsIncluded = cate.getProductsIncluded();
                List<BizSubProductInfo> bizProdList = listProductInfoFromCsvable(cate);
                bizProdList = mergeSameSku(bizProdList);
                Integer prodCount = cate.getProductCount();

                String skuAttr = cate.getSkuAttribute();
                String attrValues = null;

                if (skuAttr != null && skuAttr.length() > 0
                        && (cate.getChannelItemId() == null || cate.getChannelItemId().length() == 0))
                {
                    logger.error("uploadForBatch : ChannelItemId can not be null when skuAttr is not null");
                    bizRes = convertFailedBizProdListingInfoForUpload(cate);
                    bizList.add(bizRes);
                    continue;
                }

                if (skuAttr != null && skuAttr.length() > 0)
                {
                    skuAttr = skuAttr.replaceAll(STR_CN_COLON, STR_FOR_SPLITING_NAME_VALUE);
                    skuAttr = skuAttr.replaceAll(STR_CN_SEMICOLON, STR_FOR_SPLITING);

                    attrValues = parseSkuAttr(skuAttr);
                    if (attrValues == null || attrValues.length() == 0)
                    {
                        logger.error("uploadForBatch : parseSkuAttr failed. skuAttr=" + skuAttr);
                        bizRes = convertFailedBizProdListingInfoForUpload(cate);
                        bizList.add(bizRes);
                        continue;
                    }

                    attrValues = attrValues.toUpperCase();
                }

                String channelSku = cate.getChannelSku();
                if (attrValues != null)
                    channelSku = channelSku + SKU_ATTR_BRACKET_L + attrValues + SKU_ATTR_BRACKET_R;

                boolean isNewProdListing = false;
                DbResponse<ProductListing> proRes = productListingDbService.getProdListingBychAccIdAndchSku(new Long(
                        chAccId), channelSku);
                ProductListing record = proRes.getData();
                if (record == null)
                {
                    record = new ProductListing();
                    isNewProdListing = true;
                }

                String channelItemId = cate.getChannelItemId();
                if (channelItemId != null)
                    record.setChannelItemId(channelItemId);

                if (attrValues != null)
                    record.setSkuAttribute(skuAttr.toUpperCase());

                Integer productId = null;
                if (sku1 == null)
                {
                    BizResponse<Integer> bizResp = null;
                    String sku = cate.getSku();
                    if (parentId != null)
                    {
                        bizResp = getProductId(sku, parentId);
                        productId = bizResp.getData();
                    }
                    else
                    {
                        bizResp = getProductId(sku, accountId);
                        productId = bizResp.getData();
                    }
                    if (productId == null)
                    {
                        logger.error("uploadForBatch : getProductId failed. sku=" + sku + " accountId=" + accountId);
                        bizRes = convertFailedBizProdListingInfoForUpload(cate);
                        bizList.add(bizRes);
                        continue;
                    }
                    else
                    {
                        BizResponse<BizProductInfo> bizProRes = getProductInfo(productId);
                        BizProductInfo vp = bizProRes.getData();

                        if (vp != null && !vp.getActive())
                        {
                            logger.error("uploadForBatch : this productSku is no active. sku=" + sku + " ,count : "
                                    + prodCount);
                            bizRes = convertFailedBizProdListingInfoForUpload(cate);
                            bizList.add(bizRes);
                            continue;
                        }

                        if (vp != null && (!vp.getEssential()))
                        {
                            if (prodCount != 1)
                            {
                                logger.error("uploadForBatch : bundel product's count must equal 1. sku=" + sku
                                        + " ,count" + prodCount);
                                bizRes = convertFailedBizProdListingInfoForUpload(cate);
                                bizList.add(bizRes);
                                continue;
                            }
                        }
                    }
                }
                else if (sku1 != null && (bizProdList != null && bizProdList.size() > 0))
                {
                    prodCount = 1;
                    List<BizSubProductInfo> vSubProdList = convertProductInculdedInfo(bizProdList, accountId, parentId);
                    if (vSubProdList == null || vSubProdList.size() == 0)
                    {
                        logger.error("uploadForBatch : convertProductInculdedInfo failed.   accountId:" + accountId
                                + "   parentId:" + parentId);
                        bizRes = convertFailedBizProdListingInfoForUpload(cate);
                        bizList.add(bizRes);
                        continue;
                    }

                    Boolean firstEssentialFlag = null;
                    for (int n = 0; n < vSubProdList.size(); n++)
                    {
                        DbResponse<Product> dbProRes = productDbService.getById(new Long(vSubProdList.get(n)
                                .getProductId()));
                        Product p = dbProRes.getData();

                        if (p != null && !p.getActiveFlag())
                        {
                            logger.error("uploadForBatch : this productSku is no active. sku="
                                    + vSubProdList.get(n).getSku() + " ,count : " + vSubProdList.get(n).getQty());
                            bizRes = convertFailedBizProdListingInfoForUpload(cate);
                            bizList.add(bizRes);
                            continue outer;
                        }

                        if (n == 0)
                        {
                            firstEssentialFlag = p.getEssentialFlag();
                            if (!firstEssentialFlag)
                            {
                                if (vSubProdList.get(0).getQty() > 1)
                                {
                                    logger.error("uploadForBatch :  A display of products can only correspond to a combination product  accountId:"
                                            + accountId + "   parentId:" + parentId);
                                    bizRes = convertFailedBizProdListingInfoForUpload(cate);
                                    bizList.add(bizRes);
                                    continue outer;
                                }
                            }
                        }

                        if (firstEssentialFlag != null)
                        {
                            if (firstEssentialFlag)
                            {
                                if (!p.getEssentialFlag())
                                {
                                    logger.error("uploadForBatch :  Combination products with a single product can not occur at the same time  accountId:"
                                            + accountId + "   parentId:" + parentId);
                                    bizRes = convertFailedBizProdListingInfoForUpload(cate);
                                    bizList.add(bizRes);
                                    continue outer;
                                }
                            }
                            else
                            {
                                if (vSubProdList.size() > 1)
                                {
                                    logger.error("uploadForBatch :  A display of products can only correspond to a combination product  accountId:"
                                            + accountId + "   parentId:" + parentId);
                                    bizRes = convertFailedBizProdListingInfoForUpload(cate);
                                    bizList.add(bizRes);
                                    continue outer;
                                }
                            }
                        }
                    }

                    List<Integer> pbIdList = listProductBundleRelId(vSubProdList);
                    if (pbIdList.size() > 0)
                    {
                        DbResponse<Product> pro = null;
                        int pbFstId = pbIdList.get(0);
                        for (int j = 0; j < pbIdList.size(); j++)
                        {
                            pro = productDbService.getById(new Long(pbIdList.get(j)));
                            Product p = pro.getData();

                            if (p.getIsReal())
                            {
                                pbFstId = pbIdList.get(j);
                                break;
                            }

                        }
                        pro = productDbService.getById(new Long(pbFstId));
                        Product product = pro.getData();
                        productId = product.getId().intValue();
                    }
                    if (pbIdList.size() == 0)
                    {
                        // new a virtual product and create its product bundle
                        Product virProd = null;
                        if (parentId != null)
                            virProd = createVirtualProduct(parentId);
                        else
                            virProd = createVirtualProduct(accountId);
                        if (virProd == null)
                        {
                            logger.error("uploadForBatch : createVirtualProduct failed.");
                            bizRes = convertFailedBizProdListingInfoForUpload(cate);
                            bizList.add(bizRes);
                            continue;
                        }
                        productId = virProd.getId().intValue();
                        Boolean br = createProductBundelForVirtualProduct(productId, vSubProdList, accountId);
                        if (!br)
                        {
                            logger.error("uploadForBatch : createProductBundelForVirtualProduct failed. productId="
                                    + productId);
                            // productDbService.deleteById(new Long(productId), new Long(accountId));
                            DbResponse<Integer> dbresp = productDbService.deleteById(new Long(productId), new Long(
                                    accountId));
                            if (dbresp.hasError())
                            {
                                // roll back
                                String errorMsg = "method [productDbService.deleteById()] excute fail: "
                                        + dbresp.getErrorsToString();
                                logger.error(errorMsg);
                                rollback(errorMsg);
                            }
                            bizRes = convertFailedBizProdListingInfoForUpload(cate);
                            bizList.add(bizRes);
                            continue;
                        }
                    }
                }
                else
                {
                    logger.error("uploadForBatch : get Product info failed. sku=" + cate.getSku() + ", accountId="
                            + accountId + ", chSKU=" + cate.getChannelSku());
                    bizRes = convertFailedBizProdListingInfoForUpload(cate);
                    bizList.add(bizRes);
                    continue;
                }

                record.setChannelSku(channelSku);
                record.setChannelAccountId(new Long(chAccId));
                if (chCategory.getId() != null)
                {
                    Long channelCategoryId = chCategory.getId().longValue();
                    record.setChannelCategoryId(channelCategoryId);
                }
                record.setProductId(new Long(productId));
                DbResponse<Product> dbResponse = productDbService.getById(new Long(productId));
                Product product = dbResponse.getData();
                if (!product.getEssentialFlag() && prodCount != 1)
                {
                    logger.error("uploadForBatch : bundel product's count must equals 1. prodCount=" + prodCount
                            + " ,SKU=" + product.getProductSku());
                    bizRes = convertFailedBizProdListingInfoForUpload(cate);
                    bizList.add(bizRes);
                    continue;
                }
                record.setProductCount(prodCount);
                record.setAttributes(attributes);

                record.setProdListingTitle(cate.getTitle());
                record.setDescriptionInfo(cate.getDescription());
                record.setKeywords(cate.getKeywords());
                if (cate.getPrice() != null)
                    record.setChannelPrice(new BigDecimal(cate.getPrice()));
                if (!isNewProdListing)
                {
                    if (record.getProdListingStatus().equals(ProductListingStatus.PUBLISHING.name())
                            || record.getProdListingStatus().equals(ProductListingStatus.UPDATING.name())
                            || record.getProdListingStatus().equals(ProductListingStatus.CONFIRM_MAPPING.name())
                            || record.getProdListingStatus().equals(ProductListingStatus.REQUIRE_MAPPING.name())
                            || record.getProdListingStatus().equals(ProductListingStatus.SYNCH_CONFLICT.name()))
                    {
                        logger.error("uploadForBatch : can not modify productlisting which status is "
                                + record.getProdListingStatus() + " ,channelSKU=" + cate.getChannelSku());
                        bizRes = convertFailedBizProdListingInfoForUpload(cate);
                        bizList.add(bizRes);
                        continue;
                    }
                    else if (record.getProdListingStatus().equals(ProductListingStatus.PUBLISHED.name())
                            || record.getProdListingStatus().equals(ProductListingStatus.UPDATE_ERROR.name()))
                    {
                        record.setProdListingStatus(ProductListingStatus.MODIFY.name());
                    }
                    else if (record.getProdListingStatus().equals(ProductListingStatus.PUBLISH_ERROR.name()))
                    {
                        record.setProdListingStatus(ProductListingStatus.PUBLISH_PENDING.name());
                    }

                }
                else
                    record.setProdListingStatus(ProductListingStatus.PUBLISH_PENDING.name());
                DbResponse<Integer> dbRow = productListingDbService.save(record, new Long(accountId));
                int row = dbRow.getData();
                if (row != 1)
                {
                    logger.error("uploadForBatch : productListingDbService.save failed");
                    bizRes = convertFailedBizProdListingInfoForUpload(cate);
                    bizList.add(bizRes);
                    continue;
                }

                // BizProductListingInfo biz = convertBizProdListingFromDbModel(accountId, language, record);
                bizRes = convertSuccessBizProdListingInfoForUpload(cate);
                bizRes.setProductListingId(record.getId().intValue());
                if (!isNewProdListing)
                    bizRes.setUploadStatus(Helper.getFullName(UploadStatus.class, UploadStatus.MODIFIED.name()));
                bizList.add(bizRes);
            }
            else
            {
                logger.error("element in list should be sub class of BaseCategory.");
            }
        }
        res.setData(bizList);
        return res;
    

我自己的解决思路有两种,

1、业务层方法:开始到结束,只打开和关闭数据库一次;???? 不知如何解决

2、多线程也无法解决,(还是会去 n 次请求数据库,前台反应过来了,后台数据代码,还在跑。。。)

帮我解决;及给出 部分  或 全部代码!!

 

//此问题,非百度,谷歌所能解决;即使 能解决 花上半年时间,来网络上找在这个答案;要么我被开了,要么公司也倒闭了!!

//如有 也可以给我链接

所有回答列表(3)
cvsFeng的gravatar头像
cvsFeng  LV21 2015年9月20日

那就索性不用mybatis,在处理大量数据的时候直接用spring自身的jdbctemplete,我如果没有记错的话应该有的branch的方法,直接应对批量插入数据的问题,效率和性能应该能还可以,然后手动设置一下事务

tudou的gravatar头像
tudou  LV7 2015年9月20日

你的难点在于使用的是程序进行校验,这样无论你使用什么技术,都无法绕开这个坑。也不可避免的会在插入之前进行各种数据库连接,以及耗时的校验工作。一般程序中导入的地方并不多。

最经济省时的方法是:临时表。

1、将你的excel上传到后台。界面提示处理中,稍候发送通知给用户。这样用户所能等待的时间仅仅是上传了一个excel而已。

2、先建一张临时表(如果已存在此表,则清空),所有数据使用批处理直接保存到临时表中,没有任何校验,因为校验是耗时的。

3、制定一些规则,将符合的数据复制到真正的表里面去。不符合的数据每一条后面加上不符合的原因。

4、发送通知/站内信。通知用户上传完成结果:成功XX条,失败xx条,及每条失败的原因。

zhengdong的gravatar头像
zhengdong  LV10 2015年9月21日

还有一种方式:将所有数据直接导入到数据库,然后删掉重复或者认为不适合的数据即可。

顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友