使用EasyExcel读取Excel并存取数据库

EasyExcel读取Excel并存取数据库

配置文件

使用MyBatis-plus+SpringBoot

首先是pom依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.hxr</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>demo</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.0</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.2.6</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

yml文件

server:
  port: 8080

spring:
  datasource:
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/attendance_excel?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=Asia/Shanghai
    driver-class-name: com.mysql.cj.jdbc.Driver

mybatis-plus:
  mapper-locations: classpath:mapping/*.xml
  type-aliases-package: com.hxr.entity
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl


logging:
  level:
    com:
      example:
        mapper: debug

监听器(核心)

AttendanceDataListener.java

package com.hxr.util;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.hxr.entity.AttendanceData;
import com.hxr.service.AttendanceService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

// 有个很重要的点Listener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
public class AttendanceDataListener extends AnalysisEventListener<AttendanceData> {
    
    
    private static final Logger LOGGER = LoggerFactory.getLogger(AttendanceDataListener.class);
    /**
     * 每隔10条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
     */
    private static final int BATCH_COUNT = 10;
    List<AttendanceData> list = new ArrayList<>();



    /**
     * 根据业务需求,可以是一个DAO,也可以是一个service。当然如果不用存储这个对象没用。
     */
    private AttendanceService attendanceService;


   /* public AttendanceDataListener() {

        // 这里是demo,所以随便new一个。实际使用如果到了spring,请使用下面的有参构造函数

    }*/

	/**
	*如果要存取数据库,service从监听器里面拿取list就需要有参构造,否则直接使用会报空指针异常
	*/
    public AttendanceDataListener(AttendanceService attendanceService) {
    
    

        this.attendanceService = attendanceService;

    }

    /**
     * 这里写自己的业务,没有可以不要
     */
    private void calculateMealTimes(AttendanceData data){
    
    
    	//这里写自己的业务,没有可以不要
        doSomething();
    }



    /**
     * 这个每一条数据解析都会来调用
     * @param data
     * @param context
     */
    @Override
    public void invoke(AttendanceData data, AnalysisContext context) {
    
    
        calculateMealTimes(data);
        String result;
        result="工号:"+data.getId()+",姓名:"+data.getName()+",打卡日期:"+data.getPunchDate()
                +",打卡时间:"+data.getPunchTime()+",餐补次数:"+data.getMealSupplementTimes();
        //System.out.println(result);

		//如果数据少,这个也可以不要
        list.add(data);
        // 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
        if (list.size() >= BATCH_COUNT) {
    
    
            saveData();
            // 存储完成清理 list
            list.clear();
        }
    }


    /**
     * 所有数据解析完成了 都会来调用
     *
     * @param context
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
    
    
        // 这里也要保存数据,确保最后遗留的数据也存储到数据库
        saveData();
        LOGGER.info("所有数据解析完成!");
    }
    /**
     * 加上存储数据库
     */
    private void saveData() {
    
    
        System.out.println(list.size()+"条数据,开始存储数据库!");
        System.out.println(list);
        attendanceService.save(list);
    }


}

然后正常搭业务框架就行了。

实体类

AttendanceData.java

package com.hxr.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @author Administrator
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class AttendanceData  {
    
    

    /**
     * 部门名称
     */
    private String department;

    /**
     * 工号
     */
    private String id;

    /**
     * 员工姓名
     */
    private String name;

    /**
     *  员工类别,职等型
     */
    private String category;

    /**
     * 打卡日期
     */
    private String punchDate;

    /**
     *  当天的打卡次数
     */
    private String frequency;

    /**
     * 打卡时间
     */
    private String punchTime;

    /**
     * 时间,最早打卡和最晚打卡时间的间隔
     */
    private String totalTime;

    /**
     * 餐补次数
     */
    private String mealSupplementTimes;


}

Controller层

AttendanceController.java

package com.hxr.controller;


import com.alibaba.excel.EasyExcelFactory;
import com.hxr.entity.AttendanceData;
import com.hxr.service.AttendanceService;
import com.hxr.util.AttendanceDataListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author Administrator
 */
@RestController
public class AttendanceController {
    
    

    @Autowired
    private AttendanceService attendanceService;

    @PostMapping("/insert")
    public String insertAttendance(){
    
    


        String PATH="C:\\Users\\Administrator\\Desktop\\新建文件夹\\";
        String fileName = PATH+"0081.xls";
        // 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
        EasyExcelFactory.read(fileName, AttendanceData.class, new AttendanceDataListener(attendanceService)).sheet().doRead();
        return "添加成功!";
    }
}

Service层

AttendanceService.java

package com.hxr.service;



import com.hxr.entity.AttendanceData;

import java.util.List;


/**
 * @author Administrator
 */
public interface AttendanceService {
    
    

    /**添加数据到数据库
     * @param list
     * @return
     */
    Integer save(List<AttendanceData> list);
}

AttendanceServiceImpl.java

package com.hxr.service.impl;

import com.hxr.entity.AttendanceData;
import com.hxr.mapper.AttendanceMapper;
import com.hxr.service.AttendanceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @author Administrator
 */
@Service
public class AttendanceServiceImpl implements AttendanceService {
    
    

    @Autowired
    private AttendanceMapper attendanceMapper;

    @Override
    public Integer save(List<AttendanceData> list){
    
    

        return attendanceMapper.insertAttendance(list);
    }

}

Mapper层

AttendanceMapper.java

package com.hxr.mapper;


import com.hxr.entity.AttendanceData;
import org.springframework.stereotype.Repository;

import java.util.List;


/**
 * 假设这个是你的DAO存储。当然还要这个类让spring管理,当然你不用需要存储,也不需要这个类。
 *
 * @author Administrator*/
@Repository
public interface AttendanceMapper{
    
    

    /**将list存储到数据库中
     * @param list
     * @return
     */
    Integer insertAttendance(List<AttendanceData> list);


}

AttendanceMapper.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.hxr.mapper.AttendanceMapper">


    <insert id="insertAttendance" parameterType="java.util.List">
        insert into attendance(department,id,name,category,punch_date,frequency,punch_time,total_time,meal_supplement_times)
        values
            <foreach collection="list" item="item" separator=",">
                (#{item.department}, #{item.id},#{item.name}, #{item.category}, #{item.punchDate},#{item.frequency},#{item.punchTime}, #{item.totalTime},#{item.mealSupplementTimes} )
            </foreach>
    </insert>
</mapper>

总结

其实读都很好读,关键是将读出来的数据存取到数据库中。

在监听器中,得到的list类型是不能被Service调用的,需要在监听器中定义有参Service,然后在Controller层里面去调用。直接拿监听器里面的list使用会报空指针异常。

猜你喜欢

转载自blog.csdn.net/liuliusix/article/details/108666949