Alibaba EasyExcel的读(导入)

Alibaba EasyExcel用于导入Excel表

参考:https://www.yuque.com/easyexcel/doc/fill 官网

一、前言

书接上文(EasyExcel的导出),这里用代码案例讲下EasyExcel导入的用法。

二、使用步骤

1.涉及数据表

在这里插入图片描述
这里我们使用员工表

2.表对应的实体类

@Data
@ApiModel("员工")
public class Employe {

    @ExcelIgnore
    private Integer id;

    @ExcelProperty(value = "姓名", index = 0)
    private String name;

    @ExcelProperty(value = "年龄", index = 1)
    private Integer age;

    @ExcelProperty(value = "生日", index = 2)
    @DateTimeFormat(value = "yyyy-MM-dd")
    private Date birth;
}

这里使用的是EasyExcel中@DateTimeFormat(value = "yyyy-MM-dd")注解。可以对Excel表中日期数据,进行格式处理。

在此处有个小坑,“private Date birth;”这里birth是Date类型,所以数据库连接驱动要改成中国时间,如:“?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC”要改为“?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai”,不然下面测试数据,1997年10月1日到数据库后会变成1997-09-30;也可以将birth改为String类型,这样就不用改数据库连接驱动。

3.Controller层

@RestController
@RequestMapping("/employe")
@Api(tags = "EmployeController", description = "员工管理")
public class EmployeController {

    @Autowired
    private EmployeService employeService;

    @PostMapping("/importEmployeExcel")
    @ApiOperation("导入员工信息")
    public String importEmployeExcel(@ApiParam("导入的文件") @RequestBody MultipartFile file) {
        try {
            employeService.importEmployeExcel(file);
        } catch (Exception e) {
            e.printStackTrace();
            return "导入失败";
        }
        return "导入成功";
    }
}

其中使用到spring boot注解加swagger2注解,稍后使用swagger2进行测试

4.Service层(重点)

@Service
public class EmployeServiceImpl implements EmployeService {

    @Autowired
    private EmployeDao employeDao;

    @Override
    public void importEmployeExcel(MultipartFile file) throws Exception {
        EasyExcel.read(file.getInputStream(), Employe.class, new AnalysisEventListener<Employe>() {

            /**
             * 批处理阈值,作用:减轻数据库的压力
             */
            private static final int BATCH_COUNT = 2;

            /**
             * 存储员工对象
             */
            List<Employe> list = new ArrayList<Employe>(BATCH_COUNT);

            //easyExcel每次从Excel中读取一行数据就会调用一次invoke方法
            @Override
            public void invoke(Employe employe, AnalysisContext analysisContext) {
                list.add(employe);
                if (list.size() >= BATCH_COUNT) {
                 	employeDao.addBatch(list);
                    list.clear();
                }
            }

            //easyExcel在将Excel表中数据读取完毕后,最终执行此方法
            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                //最后,如果size<BATCH_COUNT就在这里进行数据的处理
                if (list.size() > 0) {
                    employeDao.addBatch(list);
                }
            }
			
			// 在此匿名内部类的方法里,throw new ExcelAnalysisStopException()就会终止easyExcel的运行。
			
			/**
		     *
		     * @param exception
		     * @param context
		     * @throws Exception
		     */
		    @Override
		    public void onException(Exception exception, AnalysisContext context) {
		        // 此方法能接住,在此匿名内部类的方法里抛出的异常,并进行处理,然后继续invoke方法。
		    }
		
        }).sheet().doRead();//sheet()参数指定,默认读取第一张工作表
    }
}

5.Dao层

public interface EmployeDao {
    int addBatch(List<Employe> employes);
}
<?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.expect.easyexcel.user.dao.EmployeDao">

    <insert id="addBatch" parameterType="com.expect.easyexcel.user.domain.Employe">
        insert into employe values
        <foreach collection="list" item="employe" separator=",">
            (null,#{employe.name},#{employe.age},#{employe.birth})
        </foreach>
    </insert>

</mapper>

注意:dao接口需要被扫描到才能完成映射

6.准备数据

在这里插入图片描述

注意:表头必须加,EasyExcel是从第二行开始读取数据的,亲测过。

7.数据库结果

在这里插入图片描述

至此,我们导入数据的目的达到了,可是有个小小的问题,Service层使用了匿名内部内,造成程序略显臃肿,如果是大家,大家会用什么方法呢?
下面我使用工作代码中看到的,再通过查找资料学到的一种方法。

1.首先,定义一个获取AnalysisEventListener对象的工具类

public class EasyExcelUtils {

    /**
     * @param consumer   传入一个消费者接口对象,作用:业务逻辑处理
     * @param thresshold 批处理阈值,作用:减轻数据库的压力
     * @param <T>        实体类
     * @return
     */
    public static <T> AnalysisEventListener<T> getListener(Consumer<List<T>> consumer, int thresshold) {
        return new AnalysisEventListener<T>() {
            /**
             * 存储员工对象
             */
            List<T> list = new ArrayList<T>(thresshold);

            //easyExcel每次从Excel中读取一行数据就会调用一次invoke方法
            @Override
            public void invoke(T t, AnalysisContext analysisContext) {
                list.add(t);
                if (list.size() >= thresshold) {
                    consumer.accept(list);
                    list.clear();
                }
            }

            //easyExcel在将Excel表中数据读取完毕后,最终执行此方法
            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                //最后,如果size<thresshold就在这里进行数据的处理
                if (list.size() > 0) {
                    consumer.accept(list);
                }
            }
        };
    }
}

2.把Service层改写

@Service
public class EmployeServiceImpl implements EmployeService {

    @Autowired
    private EmployeDao employeDao;

    @Override
    public void importEmployeExcel(MultipartFile file) throws Exception {
        EasyExcel.read(file.getInputStream(),Employe.class, EasyExcelUtils.getListener(this.process(),2)).sheet().doRead();
    }

    public Consumer<List<Employe>> process(){
        return employes -> employeDao.addBatch(employes);
    }

小结:这样做就是将AnalysisEventListener中的invoke方法和doAfterAllAnalysed方法代码格式固定后,不同的业务逻辑代码都在Consumer中的accept方法中完成,达到了解耦,代码也不会显得臃肿。

8.最后附上依赖

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

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!--MySQL数据库驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.16</version>
        </dependency>
        <!--MyBatis Plus 依赖-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.2</version>
        </dependency>
        <!--Swagger-UI API文档生产工具-->
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>
        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
        <!--解决Swagger 2.9.2版本NumberFormatException-->
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-models</artifactId>
            <version>1.6.0</version>
        </dependency>
        <dependency>
            <groupId>io.swagger</groupId>
            <artifactId>swagger-annotations</artifactId>
            <version>1.6.0</version>
        </dependency>

        <!--excel文件处理-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.2.6</version>
        </dependency>
        <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <version>2.4</version>
            <classifier>jdk15</classifier>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.73</version>
        </dependency>

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

三、结尾

欢迎留言。

  • 10
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值