excel导入导出

  • EasyExcel

EasyExcel导入的用法

实体类(员工表)

@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类型,这样就不用改数据库连接驱动。
**/

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 "导入成功";
    }
}

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);
                }
            }
        }).sheet().doRead();//sheet()参数指定,默认读取第一张工作表
    }
}

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>

准备数据

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

数据库结果

问题

至此,我们导入数据的目的达到了,可是有个小小的问题,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);
    }
}

原文地址:https://www.cnblogs.com/kutoutuo/p/14181504.html