EasyExcel+多线程实现大数据量

概要

大数据量Excel文件导入数据库

整体架构流程

使用多线程+EsayExcel+MyBatis批量导入实现大数据量Excel文件导入数据库

技术细节

EasyExcel

1、引入依赖

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

 版本自己看着定。

2、实现代码,基础版本

DAO

public interface MallUserDao {

        int insertBatch(@Param("entities") List<MallUser> entities);

}

 Mapper

   <insert id="insertBatch" keyProperty="id" useGeneratedKeys="true">
        insert into mall_user(user_name, user_age, user_sex, phone_number, user_mail, user_address, create_date, update_date)
        values
        <foreach collection="entities" item="entity" separator=",">
        (#{entity.userName}, #{entity.userAge}, #{entity.userSex}, #{entity.phoneNumber}, #{entity.userMail}, #{entity.userAddress}, #{entity.createDate}, #{entity.updateDate})
        </foreach>
    </insert>

 Entity

public class MallUser implements Serializable {
    private static final long serialVersionUID = 601074948288676334L;

    @ExcelIgnore
    private Integer id;
    @ExcelProperty("姓名")
    private String userName;
    @ExcelProperty("年龄")
    private String userAge;
    @ExcelProperty("性别")
    private String userSex;
    @ExcelProperty("电话")
    private String phoneNumber;
    @ExcelProperty("邮箱")
    private String userMail;
    @ExcelProperty("地址")
    private String userAddress;
    @ExcelIgnore
    private Date createDate;
    @ExcelIgnore
    private Date updateDate;


    //自己加一下get/set方法,太多了影响观文效果

}

 service

 

@Slf4j
@Service
public class ExcelImportServiceImpl implements ExcelImportService {

    @Resource
    private MallUserDao mallUserDao;


    private static final int BATCH_COUNT = 1000;

    @Override
    public void doImport() {
        log.info("进入导入逻辑");
        //需要读取的sheet数量
        int numberOfSheets = 5;
        String fileName = "item-service/src/main/resources/file/mallUser.xlsx";

        ExecutorService executorService = Executors.newFixedThreadPool(numberOfSheets);

        for (int sheetNo = 0; sheetNo < numberOfSheets; sheetNo++){
            int sheetNumber = sheetNo;
            executorService.submit(()->{
                EasyExcel.read(fileName, MallUser.class, new PageReadListener<MallUser>(dataList -> { //这里的dataList 数据量是根据BATCH_COUNT参数的大小定的
                    List cacheList = new ArrayList();
                  
                    for (MallUser mallUser : dataList) { //for循环里面可以对数据进行校验和处理
                        //数据校验
                        //设置数据的创建时间和更新时间
                        Date date = new Date();
                        mallUser.setCreateDate(date);
                        mallUser.setUpdateDate(date);
                        cacheList.add(mallUser);
                    }
                    mallUserDao.insertBatch(cacheList);//批量入库
                },BATCH_COUNT)).sheet(sheetNumber).doRead(); //这里下面这个BATCH_COUNT是设置每次读取sheet页的多少条数据到内存
                
            });
        }

        executorService.shutdown();//关闭线程池

        try {
            executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
        }catch (InterruptedException e){
            e.printStackTrace();
        }

     
    }
}

最开始的时候有两个难点:

  1、多线程读取问题
  2、批量入库问题,如果最后一批数据不足临界值怎么解决

对于第一点,EasyExcel自动实现了,sheetNumber就是读取的每一页的页数。

第二点其实也不用担心,只需要把BATCH_COUNT参数传进new PageReadListener()的构造函数就可以了,这样每次读取数据到内存中的数量就是BATCH_COUNT条,默认BATCH_COUNT=100,我这里设置成一千,最后不足一千也会读取完然后入库。

小结

        在没有任何校验逻辑的情况下,导入了90万数据,时间大概半分钟多一点,速度还是很快的。这里应该是会涉及到数据库连接池的问题,需要限制连接的数量,不能将资源都分给文件上传。

  • 22
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

何怀逸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值