使用EasyExcel将本地excel数据读取后导入mysql数据库中

本篇文章只记录EasyExcel的读(read)

一、 EasyExcel 是做什么的?

首先看下EasyExcel解释:
EasyExcel是阿里巴巴开源的一个excel处理框架,是一个基于Java的简单、省内存的读写Excel的开源项目。EasyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。

开源地址:
github地址:https://github.com/alibaba/easyexcel
(光看代码我还是有点懵懵,到小破站搜了相关视频,狂神的一个视频直接解释得一清二楚。几乎直接照着他说的做就好了,当然了要根据自己的实际情况进行适当改动。)

二、项目背景

我做的一个小项目需要把excel表中的数据导入到数据库中,然而有些数据列中还包含了很多数组对象[{…},{…},{…},{…}],而这里面的内容是要当成一个一个字段分别储存到数据库里的,因为人工或者excel都不太现实。所以就去了解了一下这个框架的使用。

excel如下:

注意:excel 不要有任何表头,因为是直接从实体类对应的参数列开始读取

三、具体使用过程

1. pom.xml 配置要加:

		 <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.2.6</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.75</version>
        </dependency>

2. 代码共有三个步骤:

  1. 创建excel对应的实体对象Dao类;
  2. 写监听器:默认是一行行的读取excel,所以需要创建excel一行一行的回调监听器,监听器主要实现了读取和储存;
  3. 调取监听器:配置好excel的位置,调取监听器读取表,然后存入数据库

步骤一:建立excel对应的实体类

ps: 使用 @ExcelProperty 注解来说明对应的excel列
在这里插入图片描述
"电阻测试数据"对应的实体类
(这里需要说明一下,我当时在excel上把这4个参数名全部替换成了对应的英文名)
在这里插入图片描述
如果最后要存到数据库里的表结构 和 excel对应的实体类有出入(比如读取到的某个字段是数组对象结构如上图excel中的"电阻测试数据",那么还需要经过处理拆分成多个字段才能分开存入数据库),那就需要额外建立一个与数据库的表对应的类(略),用于接收所有数据并存入数据库中。

数据库创建的表:在这里插入图片描述

步骤二:写监听器

监听器具体实现

/**
 * Date:2021/10/20
 * Description: excel一行一行的回调监听器
 *
 * @author ivyhu
 */
@Component
public class DemoDataListener extends AnalysisEventListener<ExcelModel> {
    
    

    @Resource
    ChargingStationMapper charingStationResistanceReportMapper;
    @Resource
    CharingStationServiceImpl charingStationServiceImpl;

    private static final Logger LOGGER = LoggerFactory.getLogger(DemoDataListener.class);

    /**
     * 有参构造
     * 如果使用了spring,请使用这个构造方法。每次创建Listener的时候需要把spring管理的类传进来
     * @param serviceImpl
     */
    public DemoDataListener(CharingStationServiceImpl serviceImpl) {
    
    
        this.charingStationServiceImpl = serviceImpl;
    }
    //无参构造
    public DemoDataListener() {
    
    
    }
    /**
     * 读取数据或执行这个invoke()方法
     * @param excelModel 类型
     * @param context    分析器
     */
    @Override
    public void invoke(ExcelModel excelModel, AnalysisContext context) {
    
    
        LOGGER.info("解析到一条数据:{}", JSON.toJSONString(excelModel));
        //最终要保存到数据库的数据
        ChargingStationModel reportModelData = new ChargingStationModel();

        String productModelNum = "";
        String itemNo = "";
        Double groundResistance = 0.0;
        Double insulationResistance = 0.0;
        Byte type = 0;
        Integer singlePilePower = 0;
        /**
         * 获取excel表中充电设施产品信息
         */
        String str1 = excelModel.getInfoData();
        JSONArray array1 = JSON.parseArray(str1);
        //如果不为空,就解析[{},{},{},{}]类型的数组对象并获取值
        if (!ObjectUtils.isEmpty(array1)) {
    
    
            for (Object obj : array1) {
    
    
                JSONObject jsonObject = (JSONObject) obj;
                ChargingStationInfoDataExcelModel infoExcelModel = JSONObject.parseObject(String.valueOf((JSONObject) obj), ChargingStationInfoDataExcelModel.class);
                type = infoExcelModel.getType();
                singlePilePower = infoExcelModel.getSinglePilePower();
            }
        }
        /**
         * 获取excel表中电阻测试数据
         */
        String str = excelModel.getResistanceData();
        JSONArray array = JSON.parseArray(str);
        //电阻测试数据不为空,就解析[{},{},{},{}]类型的数组对象并获取值
        if (!ObjectUtils.isEmpty(array)) {
    
    
            for (Object obj : array) {
    
    
                JSONObject jsonObject = (JSONObject) obj;
                ChargingStationResistanceDataExcelModel reportModel = JSONObject.parseObject(String.valueOf((JSONObject) obj), ChargingStationResistanceDataExcelModel.class);
                productModelNum = reportModel.getProductModelNum();
                itemNo = reportModel.getItemNo();
                groundResistance = reportModel.getGroundResistance();
                insulationResistance = reportModel.getInsulationResistance();
                //插入数据到数据库
                reportModelData = new ChargingStationModel(excelModel.getReportNo(), excelModel.getModelNum(), productModelNum, itemNo, groundResistance, insulationResistance, type, singlePilePower,
                        excelModel.getOutputVoltageControlErrorOfCharger(), excelModel.getOutputCurrentControlErrorOfCharger(), excelModel.getActiveStopChargeTestOutputCurrentStopRate(), excelModel.getPassiveStopChargeTestOutputCurrentStopRate(),
                        excelModel.getChargerOutputCurrentAdjustmentTimeAbove20A(), excelModel.getChargerOutputCurrentAdjustmentTimeUnder20A(), excelModel.getImpulseCurrent());
                saveData(reportModelData);
            }
        }
    }

    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
    
    

        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        /*saveData();*/
        LOGGER.info("所有数据解析完成!");
    }

    /**
     * 加上存储数据库
     */
    private void saveData(ChargingStationModel resistanceReportModel) {
    
    
        //调用mapper插入数据库
        charingStationServiceImpl.save(resistanceReportModel);
    }


}

步骤三:调取监听器读取数据
1. Controller层

@RestController
@Controller
@RequestMapping("/product/charging_station")
public class ChargingStationController {
    
    

    @Resource
    CharingStationService charingStationService;
    /**
     * 提取excel表格数据的接口
     */
    @PostMapping()
    public void saveExcel(){
    
    
        charingStationService.saveData();
    	}
    }

2. Service层

@Service
public class CharingStationServiceImpl implements CharingStationService {
    
    

    @Resource
    ChargingStationMapper chargingStationMapper;
    @Resource
    ExcelUtil excelUtil;
    @Resource
    ChargingStationAcceptanceValueMapper chargingStationAcceptanceValueMapper;

    /**
     * 调用读取excel数据的方法
     */
    @Override
    public void saveData() {
    
    
        excelUtil.excelRead();
    }

3. 监听器入口
设置好文件地址、文件名、excel对应的实体类

扫描二维码关注公众号,回复: 14912819 查看本文章
@Component
public class ExcelUtil {
    
    

    @Autowired
    private CharingStationServiceImpl charingStationServiceImpl;
    /**
     * 最简单的读
     * 1. 创建excel对应的实体对象 ExcelModel
     * 2. 由于默认一行行的读取excel,所以需要创建excel一行一行的回调监听器,参照{@link DemoDataListener}
     * 3. 直接读即可
     */
    private static final Logger LOGGER = LoggerFactory.getLogger(ExcelUtil.class);
    
    //文件位置
    String PATH = "D:\\excelTest\\";


    public void excelRead() {
    
    

        // 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
        String fileName = PATH + "充电桩验收测试数据.xlsx";
        // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
        EasyExcel.read(fileName, ExcelModel.class, new DemoDataListener(charingStationServiceImpl)).sheet().doRead();

    }
}

本文知识点:

  1. 转化Json,解析[{},{},{},{}]类型的数组对象获取里面的单个内容
JSONObject jsonObject = (JSONObject) obj;
ChargingStationResistanceDataExcelModel reportModel = JSONObject.parseObject(String.valueOf((JSONObject) obj);
  1. 使用注解@Component将DemoDataListener和监听器入口交给Spring来管
@Component
public class DemoDataListener extends AnalysisEventListener<ExcelModel> {
    
    
...
}
  1. 配置好要读取的文件位置
//文件位置
    String PATH = "D:\\excelTest\\";

    public void excelRead() {
    
    

        // 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
        String fileName = PATH + "充电桩验收测试数据.xlsx";

        // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
        EasyExcel.read(fileName, ExcelModel.class, new DemoDataListener(charingStationServiceImpl)).sheet().doRead();

    }

ps: 一开始运行的时候报了几个错:

  1. mapper报空指针。两个可能,查了一下发现一是因为没有将DemoDataListener和监听器入口类注入Spring,导致无法找到bean,需要使用@Component。二是没有通过Spring mvc的模型调用, 只是套用了开源框架中的单元测试@Test运行。
  2. 读取文件失败,因为没有把文件头那栏删掉。

此文只是小菜鸡的一点点记录,有错望各位大佬指正!

猜你喜欢

转载自blog.csdn.net/Ivy_Xinxxx/article/details/121036543