锋盈数科-知识库 Logo
首页
软件开发
计算机基础
Hello Halo
新手必读
关于本知识库
登录 →
锋盈数科-知识库 Logo
首页 软件开发 计算机基础 Hello Halo 新手必读 关于本知识库
登录
  1. 首页
  2. 软件开发
  3. 数据库
  4. EasyExcel批量读取Excel文件数据导入到MySQL表中

EasyExcel批量读取Excel文件数据导入到MySQL表中

0
  • 数据库
  • 发布于 2024-09-26
  • 14 次阅读
黄健
黄健

1、EasyExcel简介

官网:EasyExcel官方文档 - 基于Java的Excel处理工具 \| Easy Excel 官网

2、代码实战

首先引入jar包

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

2.1 读取Excel

2.1.1 使用PageReadListener

这种方式代码简洁,通俗易懂,直接看示例:

 public void readExcelFile2(MultipartFile file) {
    AtomicInteger count = new AtomicInteger(0);
    try {
          int batch = 10;
          EasyExcel.read(file.getInputStream(), SharePathApproveModule.class, new PageReadListener<SharePathApproveModule>(list -> {
             System.out.println("已完成" + list.size() + "条数据读取...");
             for (SharePathApproveModule module : list) {
                  System.out.println("读取到" + count.incrementAndGet() + "条数据=>" + JSONObject.toJSONString(module));

              }
              //批量写入
              //sharePathApproveMapper.insertBatch(list);
          }, batch)).sheet(0).doRead();
          //sheetNo参数不传默认0,读取第一个sheet;填0也是读取第1个sheet;填1即读取第2个sheet
      } catch (Exception e) {
          log.error("读取Excel数据异常,", e);
      }
  }

这种方式是直接使用了PageReadListener监听器,有兴趣的同学可以自行解读PageReadListener源码,这里我只把源码粘贴出来,本文主要讲实战,就不过多说PageReadListener。

import java.util.List;
import java.util.function.Consumer;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.util.ListUtils;

import org.apache.commons.collections4.CollectionUtils;

/**
 * page read listener
 *
 * @author Jiaju Zhuang
 */
public class PageReadListener<T> implements ReadListener<T> {
    /**
     * Default single handle the amount of data
     */
    public static int BATCH_COUNT = 100;
    /**
     * Temporary storage of data
     */
    private List<T> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
    /**
     * consumer
     */
    private final Consumer<List<T>> consumer;

    /**
     * Single handle the amount of data
     */
    private final int batchCount;

    public PageReadListener(Consumer<List<T>> consumer) {
        this(consumer, BATCH_COUNT);
    }

    public PageReadListener(Consumer<List<T>> consumer, int batchCount) {
        this.consumer = consumer;
        this.batchCount = batchCount;
    }

    @Override
    public void invoke(T data, AnalysisContext context) {
        cachedDataList.add(data);
        if (cachedDataList.size() >= batchCount) {
            consumer.accept(cachedDataList);
            cachedDataList = ListUtils.newArrayListWithExpectedSize(batchCount);
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        if (CollectionUtils.isNotEmpty(cachedDataList)) {
            consumer.accept(cachedDataList);
        }
    }

}

简单的说一下PageReadListener监听器的两个方法:invoke和doAfterAllAnalysed;他们都是实现ReadListener接口里面定义的方法。

invoke:表示每解析完一条数据就会调用该初始方法,因此很多条件筛选或业务我们可以放在里面实现。

doAfterAllAnalysed:表示每解析完一个sheet页后调用该方法。

从源码中知道,invoke()中当数组的长度大于等于设置的长度时,则执Consumer,执行完成后在进行初始化集合;

doAfterAllAnalysed()中在获取完数据后,判断当前集合时候还有数据,有的话则执行Consumer。

2.1.2 自定义监听器

我们可以通过继承AnalysisEventListener类来自定义监听器,重新里面的invoke和doAfterAllAnalysed方法。

首先,新建一个Module

/**
 * @description
 * @date 2024-07-10 18:02
 **/
@Data
public class ShareModule {

    @ExcelProperty(value = "share路径", index = 0)
    @ColumnWidth(value = 10)
    private String sharePath;

    @ExcelProperty(value = "权限", index = 1)
    @ColumnWidth(value = 10)
    private String access;

    @ExcelProperty(value = "组名", index = 2)
    @ColumnWidth(value = 10)
    private String groupCn;

    @ExcelProperty(value = "历史申请人", index = 3)
    @ColumnWidth(value = 20)
    private String applicants;
}

接着,定义Mapper和Mapper.xml,这里我们只写一个批量插入的方法,使用

insert into table_name(column1,column2,column3) values(x,x,x),(x,x,x),…..

这种方式减少了数据库的连接,提高插入效率,而mybatis这样执行批处理需要在数据库url配置上添加rewriteBatchedStatements=true,进行批处理开启。

public interface ShareMapper {

    int insertBatch(@Param("shareModules")List<ShareModule> shareModules);

    int clearTableData();
}
```XML
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.example.demo.mapper.ShareMapper">

    <insert id="insertBatch">
        INSERT INTO share_path_approve (share_path, access, group_cn, applicants) VALUES
        <foreach collection="shareModules" index="index" item="po" separator=",">
            (#{po.sharePath}, #{po.access}, #{po.groupCn}, #{po.applicants})
        </foreach>
    </insert>

    <update id="clearTableData">
        truncate table share_path_approve
    </update>

</mapper>

然后,就是自定义监听器,配将这个监听器交给Spring容器

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.example.wangpeng.mapper.SharePathApproveMapper;
import com.example.wangpeng.po.module.SharePathApproveModule;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

/**
 * @description share auto
 * @date 2024-07-10 10:30
 */
@Slf4j
public class ShareListener extends AnalysisEventListener<ShareModule> {

    private List<ShareModule> cacheData = new ArrayList<>();
    private static final int BATCH_COUNT = 8;

    private final ShareMapper shareMapper;

    public SharePathApproveListener(ShareMapper shareMapper) {
        this.shareMapper= shareMapper;
    }


    @Override
    public void invoke(ShareModule shareModule, AnalysisContext analysisContext) {
        cacheData.add(shareModule);
        if (cacheData.size() >= BATCH_COUNT) {
            log.info("保存数据--share auto-----{}条", cacheData.size());
            saveData();
            // 可以清理缓存数据
            cacheData = new ArrayList<>();
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        // 处理最后未达到8条数据的插入
        if (!cacheData.isEmpty()) {
            log.info("保存数据--share auto-----{}条", cacheData.size());
            saveData();
        }
    }

    private void saveData() {
        // 这里可以使用MyBatis的批量插入方法
        shareMapper.insertBatch(cacheData);
    }
}
```java
import com.example.wangpeng.excel.SharePathApproveListener;
import com.example.wangpeng.mapper.SharePathApproveMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @description
 * @date 2024-07-10 18:17
 */
@Configuration
public class EasyExcelConfig {

    @Bean
    public ShareListener shareListener(ShareMapper shareMapper) {
        return new shareListener(shareMapper);
    }
}

最后一步,就是编写Service和实现类、控制层接口代码

public interface ExcelService {

    ResponseResult<?> importExcel(MultipartFile file, Integer type);

}
```java
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSONObject;
import com.example.demo.excel.ShareListener;
import com.example.demo.mapper.ShareMapper;
import com.example.demo.po.module.ShareModule;
import com.example.demo.response.ResponseResult;
import com.example.demo.service.ExcelService;
import lombok.extern.log4j.Log4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;


/**
 * @description
 * @date 2024-06-03 15:57
 */
@Log4j
@Service
public class ExcelServiceImpl implements ExcelService {

    @Autowired
    private SharePathApproveMapper sharePathApproveMapper;


    @Override
    public ResponseResult<?> importExcel(MultipartFile file, Integer type) {

        try (InputStream inputStream = file.getInputStream()) {
            if (0 == type) {
                //全量覆盖
                sharePathApproveMapper.clearTableData();
            }  //增量插入

            EasyExcel.read(inputStream, ShareModule.class, new ShareListener(shareMapper))
                    .sheet()
                    .doRead();

            return ResponseResult.success();
        } catch (Exception e) {
            log.info("ShareExcel并解析 异常!", e);
            return ResponseResult.fail(e.getMessage());
        }
    }
}
```java

@RestController
@RequestMapping(value = "/excel")
public class ExcelController {

    @Autowired
    private ExcelService excelService;

    @PostMapping(value = "/import")
    public ResponseResult<String> excelFile2(@RequestBody MultipartFile file, Integer type) {
        excelService.importExcel(file, type);
        return ResponseResult.success();
    }
}

运行如下:

原文链接: https://onlyou.blog.csdn.net//article/details/140332965

标签: #数据库 67 #MySQL 49
相关文章

深入理解MySQL InnoDB中的B+索引机制 2024-09-30 14:41

目录 一、InnoDB中的B+ 树索引介绍 二、聚簇索引 (一)使用记录主键值的大小进行排序

mysql中B+树的数据存储 2024-09-29 16:36

B+树索引基础分析 B+树 的定义 B+树是一种自平衡的树形数据结构,常用于数据库和操作系统的索引结构。它具有以下特点: 所有数据都存储在叶子节点,非叶子节点仅存储键值和子节点的指针。 叶子节点之间通过指针相互连接,形成一个有序链表,便于范围查询。 每个节点可以拥有多个键值,键值之间是有序的。 B+

MySQl索引事务(B树) 2024-09-29 16:36

目标: 索引 事务 1.索引 1.1概念 索引是一种特殊的文件,包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引,并指定索引的类型,各类索引有各自的数据结构实现。 1.2作用 数据库中的表、数据、索引之间的关系,类似于书架上的图书、书籍内容和书籍目录的关系。 索引所起的作用类似书籍

MySQL数据库的备份与恢复 2024-09-26 17:57

MySQL数据库的备份与恢复 在现代信息时代,数据已成为企业和个人的重要资产,数据的安全性和可恢复性直接影响到业务的连续性和稳定性。MySQL作为广泛使用的关系型数据库管理系统,其数据的备份与恢复显得尤为重要。本文将详细探讨MySQL数据库的备份与恢复策略,包括备份的重要性、备份类型、常用备份方法及

MySQL中创建数据库和表 2024-09-26 17:57

在MySQL中创建数据库和表是数据库管理的基础步骤,它们构成了数据存储和操作的基础结构。下面,我将详细介绍如何在MySQL中创建数据库和表,包括创建数据库的基本语法、设计表的考虑因素、表的创建过程、数据类型和约束的使用等,力求内容详尽且不少于2000字。 一、创建数据库 在MySQL中,数据库是一个

MySQL数据库主从搭建(详细图文) 2024-09-28 15:11

MySQL数据库主从搭建(详细图文) 前言 主从原理: MySQL之间数据复制的基础是二进制日志文件(binary log file)。一台MySQL数据库一旦启用二进制日志后,其作为master,它的数据库中所有操作都会以"事件"的方式记录在二进制日志中,其他数据库作为slave通过一个I/O线程

目录

IT 外包服务商

  • 意见投递
  • zyf6619

软件开发应用

主菜单

  • 首页
  • 软件开发
  • 计算机基础
  • Hello Halo
  • 新手必读
  • 关于本知识库
Copyright © 2024 your company All Rights Reserved. Powered by Halo.