当前位置: 首页 > article >正文

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

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

    • 1.导入依赖
    • 2. 构建实体类
    • 3.Controller层
    • 4.Service层

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);
            }
        }

    }

}


http://www.kler.cn/news/327747.html

相关文章:

  • Python人工智能使用OpenCV进行图片形状的中心检测
  • linux 查看端口占用
  • 利用SpringBoot构建高效社区医院平台
  • 大数据埋点方案Openresty+Nginx+Lua踩坑日志
  • QSpice (9) --结合Python仿真
  • PostgreSQL是否有等待事件
  • Android常用C++特性之std::abs
  • Clickhouse分布式表初体验
  • python的内存管理机制
  • DOM元素导出图片与PDF:多种方案对比与实现
  • 数据集-目标检测系列-豹子 猎豹 检测数据集 leopard>> DataBall
  • 线程池:线程池的实现 | 日志
  • 普通人如何在未来市场中寻找赚钱机会?
  • 深信服2025届全球校招研发笔试-C卷(AK)
  • UE4/UE5开发资源
  • pyqt QGraphicsView 以鼠标为中心进行缩放
  • uniapp中实现评分组件,多用于购买商品后,对商品进行评价等场景
  • 数据结构-AC自动机
  • python 实现矩阵的Schur complement舒尔补算法
  • Goland无法使用debug的修复
  • 【源码+文档+调试讲解】无人超市系统python
  • 【Docker】02-数据卷
  • 【研1深度学习】《神经网络和深度学习》阅读笔记(记录中......
  • 博弈论(学习笔记)
  • RK3568 android11 适配鼎桥MT5710-CN 5G模块
  • 墙绘产品在线展示:SpringBoot技术的应用
  • 数据结构——对顺序线性表的操作
  • docker 私有仓库的镜像删除
  • 基于SSM的O20兼职系统的设计与实现(源码+定制+文档)
  • Windows下安装 LLama-Factory 保姆级教程