使用Hutool批量导入excel数据

前言:在实际工作中,遇到了数据导入问题。我这里使用了Hutool工作包的excel导入方法,下面是实现代码。

代码实现:
controller层:

@PostMapping("/uploadFile")
    public JSONObject upload(@RequestParam("file")MultipartFile file) throws IOException {
        JSONObject result = this.dataSharingDylwhzService.upload(file);
        return result;
    }

service层:

/**
     * 文件上传(使用hutool进行批量上传,适用于小批量的数据上传,如果上传的excel大于10MB,则会报错内存溢出错误,使用easyExcel技术即可解决)
     * @param file: 上传的文件
     * @return
     */
    @Override
    @Transactional
    public JSONObject upload(MultipartFile file) throws IOException {
        //获取当前用户名
        String userName = SwbUserSecurityUtil.getInstance().getSwbUser().getUserName();
        //获取当前时间
        Date date = new Date();

        //创建一个存放返回结果的对象
        JSONObject result = new JSONObject();
        AjaxBackData ajax = null;

        // 通过文件获取输入流
        InputStream in = file.getInputStream();
        // 调用 hutool 方法读取数据 默认调用第一个sheet
        ExcelReader reader = ExcelUtil.getReader(in);

        try {
            //对上传的文件进行验证
            if (Objects.isNull(file) || Objects.isNull(file.isEmpty())){
                ajax = new AjaxBackData(false,"上传文件不能为空,请重新上传!");
            }else { //上传的文件无误,可以上传
                //忽略第一行头(第一行是中文的情况),直接读取表的内容
                List<List<Object>> list = reader.read(1);
                //创建一个新的ArrayList
                List<DataSharingDylwhz> dylwhzList = CollUtil.newArrayList();
                //循环遍历数据
                for (List<Object> row : list) {
                    DataSharingDylwhz dylwhz = new DataSharingDylwhz();
                    dylwhz.setId(IdUtil.simpleUUID()); //使用UUID对象用于生成主键
                    dylwhz.setSbny(row.get(1).toString());
                    dylwhz.setNyzwrs(Integer.valueOf(row.get(2).toString()));
                    dylwhz.setYgzwrs(Integer.valueOf(row.get(3).toString()));
                    dylwhz.setNyzzzwrs(Integer.valueOf(row.get(4).toString()));
                    dylwhz.setCreateName(userName);
                    dylwhz.setCreateTime(date);
                    dylwhzList.add(dylwhz);
                }
                //循环遍历dylwhzList集合,找出数据库中是否有已经存在的数据
                for (DataSharingDylwhz dylwhz : dylwhzList) {
                    String sbny = dylwhz.getSbny();
                    //判断上报年月是不为null或空则查询删除数据
                    if (StringUtils.isNotBlank(sbny)){
                        //通过这几个条件判断数据库中是否存在该数据
                        List<String> ids = this.dataSharingDylwhzDao.getDataIdsByCondition(sbny);
                        //如果数据库中存在,则删除数据库中存在的数据
                        if (!ids.isEmpty()){
                            this.dataSharingDylwhzDao.deleteByIds(ids);
                        }
                    }
                }

                //批量插入数据
                log.info("===== 开始插入数据 =====");
                long startTime = System.currentTimeMillis();
                //创建一个集合,用于临时存放数据
                ArrayList<DataSharingDylwhz> temporaryList = new ArrayList<>();
                //循环插入全部数据,每1000条数据往临时集合中存放一次,然后执行批量插入方法,之后清空临时集合,以此往复
                for (int i = 0; i < dylwhzList.size(); i++){
                    //将当前数据添加到临时集合中
                    temporaryList.add(dylwhzList.get(i));
                    //每1000次执行一次批量插入操作
                    if ((i + 1) % 1000 == 0){
                        //批量插入方法
                        this.dataSharingDylwhzDao.batchSave(temporaryList);
                        //清空临时集合
                        temporaryList.clear();
                    }
                }
                //处理剩余的数据(不足1000条的情况)
                if (!temporaryList.isEmpty()) {
                    this.dataSharingDylwhzDao.batchSave(temporaryList);
                }
                //插入数据用时
                long spendTime = System.currentTimeMillis() - startTime;
                log.info("===== 成功插入" + dylwhzList.size() + "条数据,耗时:" + spendTime + "毫秒");
                ajax = new AjaxBackData(true, "上传成功!");
            }
        }catch (UncategorizedSQLException e){
            SQLException sqlException = e.getSQLException();
            int errorCode = sqlException.getErrorCode();
            if (errorCode == 12899){
                ajax = new AjaxBackData(false, "上传失败,请检查数据内容大小,修改后重试!");
            }
            e.printStackTrace();
        }catch (DataIntegrityViolationException e){
            Throwable cause = e.getCause();
            //instanceof 是一个关键字,用于测试一个对象是否是一个类的实例或者是该类的子类的实例
            if (cause instanceof SQLException){
                SQLException sqlException = (SQLException) cause;
                int errorCode = sqlException.getErrorCode();
                if (errorCode == 1722){
                    ajax = new AjaxBackData(false, "上传失败,请检查数据格式,修改后重试!");
                }
            }else {
                ajax = new AjaxBackData(false, "上传出现异常,请稍后重试!");
            }
            e.printStackTrace();
        }catch (Exception e){
            ajax = new AjaxBackData(false, "上传失败,请稍后重试!");
            e.printStackTrace();
        }finally {
            //关闭流对象
            reader.close();
            in.close();
        }
        result.put("ajax", ajax);
        return result;
    }

控制台输出:

===== 开始插入数据 =====
===== 成功插入15562条数据,耗时:5000毫秒

这段代码的核心是:
ExcelReader reader = ExcelUtil.getReader(in);
使用 Hutool中的ExcelUtil.getReader()方法将实体Excel文件转换为Hutool封装的ExcelReader对象。后续可以通过这个对象读取excel文件的内容。

注意:
当上传的excel数据量过大时(大于10MB),就不能使用这个方法了,因为这个方法会读取Excel会非常缓慢,在内存中加载大量数据,尤其是当整个文件的内容都被加载到内存中时,可能会导致内存不足。抛出java.lang.OutOfMemoryError: GC overhead limit exceeded异常并造成内存溢出错误。那么当我们在上传大批量的数据时,可以考虑使用easyExcel插件处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值