自学内容网 自学内容网

Springboot项目实现easyExcel批量导入到数据库

Springboot项目实现easyexcel批量导入到数据库

1.导入依赖

      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>easyexcel</artifactId>
          <version>3.0.5</version>
      </dependency>

2. 构建实体类

注意:

  1. 在导入数据的时候 在excel表中的列名顺序要和实体类中的字段顺序一致,它会按照顺序进行一一导入数据,如果顺序不一致,会导致传入的值和字段对应不上的情况;
  2. 如果有字段不需要导入,可以使用注解@ExcelIgnore忽略;
  3. @ExcelProperty中的值也要和excel表中的列名称完全对应;

以下是我的实体类:

@Data
public class LayerMessage {

    private Integer markerId;

    @ExcelProperty("图层名称")
    private String markerName;

    private String descInfo;

    @ExcelProperty("备注")
    private String remark;

    @ExcelProperty("操作时间")
    private Date opDate;

    @ExcelIgnore
    private Integer isDel;

3.Controller层

@PostMapping(value = "/import")
    @ApiOperation(value = "批量导入")
    public R importLayer(@RequestPart("layerfile") MultipartFile layerfile){
        return layerManagementService.importLayer(layerfile);
    }

若是项目中没有配置swagger不需要写@ApiOperation注解

4.Service层

/**
     * 批量导入
     * @param layerfile
     */
    @Override
    public R importLayer(MultipartFile layerfile) {
        try{
            logger.info("开始导入:{}", layerfile.getOriginalFilename());
//            LayerMessageListener layerMessageListener = new LayerMessageListener();
            layerMessageListener.setRes(new ArrayList<>());
            layerMessageListener.setCount(0);
            EasyExcel.read(layerfile.getInputStream(),LayerMessage.class,layerMessageListener).sheet().doRead();
            return layerMessageListener.resMess();
        }catch (Exception e){
            throw new ValidateException("导入失败");
        }
    }

在service中为了返回详细的错误提示,在读取数据之前,先将存储错误信息的list以set的形式给初始化;在数据插入结束之后调用listener中的函数返回错误信息。
对数据的插入部分我写到了listener中,也可以写到Service中。

Listener文件如下:

@Component
@Scope("prototype")
@Slf4j
public class LayerMessageListener extends AnalysisEventListener<LayerMessage> {

    @Autowired
    private LayerMessageMapper layerMessageMapper;

    /**
     * 每隔100条处理下,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 100;

    //计数
    @Setter
    private int count;

    /**
     * 缓存的数据
     */
    private List<Map<Integer,LayerMessage>> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);

    //导入失败的错误提示集合
    @Setter
    private List<String> res;

    public LayerMessageListener(){
        this.res = new ArrayList<>();
    }

    //一行一行去读取excel内容并封装到LayerMessageDto中
    //默认从第二行读取数据,因为第一行一般都是表头
    @Override
    public void invoke(LayerMessage layerMessage, AnalysisContext analysisContext) {
        //获取行号
        int index=analysisContext.readRowHolder().getRowIndex();

        log.info("解析到第{}行的数据:{}",analysisContext.readRowHolder().getRowIndex(),layerMessage);
        count++;
        //缓存解析的数据
        Map<Integer,LayerMessage> map = new HashMap<>();
        map.put(index,layerMessage);
        cachedDataList.add(map);

        //达到批量处理的数据量,进行批量插入数据库
        if(cachedDataList.size() >= BATCH_COUNT){
            save(cachedDataList);
            //插入完之后清空缓存
            cachedDataList.clear();
        }
    }

    //解析完成后执行收尾工作
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        log.info("sheet={} 所有数据解析完成!", analysisContext.readSheetHolder().getApproximateTotalRowNumber()-1);
        //将缓存中剩余的数据保存到数据库中
        save(cachedDataList);
        //清空缓存
        cachedDataList.clear();
    }

    //返回错误信息
    public R resMess(){

        log.info("添加失败{}条数据,count:{}",res.size(),count);
        if(res!=null && res.isEmpty()){
            return R.ok("全部添加成功");
        }else if(res != null && res.size()==count){
            return R.failed(res,"全部添加失败");
        }else{
            return R.failed(res,"部分添加失败");
        }
    }

    //添加数据
    void save(List<Map<Integer, LayerMessage>> layerMessagelist){

//此处为了将excel中的行号与内容对应起来,我使用了map的结构
        for(Map<Integer,LayerMessage> layerMessagemap:layerMessagelist){
            for(Map.Entry<Integer,LayerMessage> entry:layerMessagemap.entrySet()){
                int rowindex=entry.getKey();
                LayerMessage layerMessage=entry.getValue();

                //此处可以写对excel中导入的内容的校验逻辑

                //检查“markerDataId”是否已经存在于数据库中
                List<String> list = layerMessageMapper.markerDataIdAll();
                List<String> list1 = layerMessageMapper.selectCodeList(layerMessage.getAreaCode());
                if (list1.contains(layerMessage.getAreaCode())){
                    res.add("第"+rowindex+"行错误");
                    continue;
                }
                  
                //将新层消息插入数据库
                layerMessageMapper.insertLayerMessage(layerMessageDto);
            }
        }

    }

}


原文地址:https://blog.csdn.net/qq_53844452/article/details/142589515

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!