线程池+监听器+easyExcel 实现excel数据快速导入数据库

线程池+监听器+easyExcel 实现excel数据快速导入数据库

 <!-- alibaba excel依赖 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.2.6</version>
            <exclusions>
                <exclusion>
                    <artifactId>cglib</artifactId>
                    <groupId>cglib</groupId>
                </exclusion>
            </exclusions>
        </dependency>

使用监听器实现excel文件导入

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.cbb.gyl_serve.bean.ob.GylOrderDetailWithBLOBs;
import com.cbb.gyl_serve.dao.ob.GylOrderDetailMapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
public class GylOrderDetailListener extends AnalysisEventListener<GylOrderDetailWithBLOBs> {

    private List<GylOrderDetailWithBLOBs> cacheData = new ArrayList<>();
    private static final int BATCH_COUNT = 5000;

    private static AtomicInteger count = new AtomicInteger(1);
    private final GylOrderDetailMapper orderDetailMapper;
  

    public GylOrderDetailListener(GylOrderDetailMapper orderDetailMapper) {
        this.orderDetailMapper= orderDetailMapper;
    }



    @SneakyThrows
    @Override
    public void invoke(GylOrderDetailWithBLOBs orderDetailWithBLOBs, AnalysisContext analysisContext) {
        Calendar calendarType4 = Calendar.getInstance();
        calendarType4.add(Calendar.YEAR, -3);
        Date time = calendarType4.getTime();
        SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd");
        Date Orderdate = format.parse(orderDetailWithBLOBs.getOrderTime());
        if(Orderdate.compareTo(time)>=0){
            cacheData.add(orderDetailWithBLOBs);
        }
        if (cacheData.size() >= BATCH_COUNT) {
            log.info("保存数据--share auto-----{}条", cacheData.size());
            saveData();
            cacheData.clear();
        }
    }

    @SneakyThrows
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        if (!orderDetailList.get().isEmpty()) {
            log.info("保存数据--share auto-----{}条", orderDetailList.get().size());
            saveData();
        }

    }
    private void saveData() {
        // 这里可以使用MyBatis的批量插入方法
        orderDetailMapper.insertBatchOrderDetail(cacheData);
    }

 

 

}

到这里解决了excel大文件内存溢出问题,但是导入数据库数据慢,引入线程池实现快速批量导入

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.read.listener.ReadListener;
import com.cbb.gyl_serve.bean.ob.GylOrderDetailWithBLOBs;
import com.cbb.gyl_serve.dao.ob.GylOrderDetailMapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;

@Slf4j
public class GylOrderDetailListener extends AnalysisEventListener<GylOrderDetailListener > {
    private List<GylOrderDetailWithBLOBs> cacheData = new ArrayList<>();
    private static final int BATCH_COUNT = 5000;
    private ExecutorService executorService = Executors.newFixedThreadPool(10);
    private ThreadLocal<ArrayList<GylOrderDetailWithBLOBs>> orderDetailList = ThreadLocal.withInitial(ArrayList::new);
    private static AtomicInteger count = new AtomicInteger(1);
    private final GylOrderDetailMapper orderDetailMapper;
    @Autowired
    //线程池
    private ThreadPoolExecutor executor;

    public GylOrderDetailListener (GylOrderDetailMapper orderDetailMapper) {
        this.orderDetailMapper= orderDetailMapper;
    }



    @SneakyThrows
    @Override
    public void invoke(com.cbb.gyl_serve.bean.ob.GylOrderDetailWithBLOBs orderDetailWithBLOBs, AnalysisContext analysisContext) {
        Calendar calendarType4 = Calendar.getInstance();
        calendarType4.add(Calendar.YEAR, -3);
        Date time = calendarType4.getTime();
        SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd");
        Date Orderdate = format.parse(orderDetailWithBLOBs.getOrderTime());
        String formattedDate = format.format(time);
        Date nowTime = format.parse(formattedDate);
        if(Orderdate.compareTo(nowTime)>=0){
            orderDetailList.get().add(orderDetailWithBLOBs);
        }
        if (orderDetailList.get().size() >= BATCH_COUNT) {
            log.info("保存数据--share auto-----{}条", orderDetailList.get().size());
//            saveData();
//            cacheData.clear();
             asyncSaveData();
        }
    }

    @SneakyThrows
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        if (!orderDetailList.get().isEmpty()) {
            log.info("保存数据--share auto-----{}条", orderDetailList.get().size());
            asyncSaveData();
        }
        executorService.shutdown();
        //等待线程池执行完毕
        while(!executorService.isTerminated()){
        }
        count.set(1);
        System.out.println("线程池执行完毕");
    }


    public void asyncSaveData() throws ExecutionException, InterruptedException {
        if (!orderDetailList.get().isEmpty()) {
            ArrayList<GylOrderDetailWithBLOBs> OrderDetailDOS = (ArrayList<GylOrderDetailWithBLOBs>) orderDetailList.get().clone();
            executorService.execute(new GylOrderDetailListener .SaveTask(OrderDetailDOS,orderDetailMapper));
            orderDetailList.get().clear();
        }
    }

    static class SaveTask implements Runnable {

        private List<GylOrderDetailWithBLOBs> employeeList;
        private GylOrderDetailMapper orderDetailMapper;
        public SaveTask(List<GylOrderDetailWithBLOBs> employeeList, GylOrderDetailMapper orderDetailMapper) {
            this.employeeList = employeeList;
            this.orderDetailMapper = orderDetailMapper;
        }

        @Override
        public void run() {
            orderDetailMapper.insertBatchOrderDetail(employeeList);
//            Thread.currentThread().getId();
//            log.info("线程"+Thread.currentThread().getId()+","+new Date()+"插入"+employeeList.size() + "条数据");
            log.info("线程"+Thread.currentThread().getId()+"第" + count.getAndAdd(1) + "次插入" + employeeList.size() + "条数据");
        }
    }

}

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这里是SpringBoot+Mybatis-plus整合easyExcel批量导入Excel数据库+导出Excel的方法。 1. 添加依赖 在 pom.xml 文件中添加以下依赖: ```xml <!-- easyExcel --> <dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>2.1.6</version> </dependency> <!-- mybatis-plus --> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.2</version> </dependency> ``` 2. 创建实体类 创建一个实体类,用于映射 Excel 表格中的数据。 ```java @Data public class User { @ExcelProperty("姓名") private String name; @ExcelProperty("年龄") private Integer age; @ExcelProperty("性别") private String gender; } ``` 3. 创建Excel读取器 创建一个 Excel 读取器,用于读取 Excel 表格中的数据,并将数据存储到数据库中。 ```java @Component public class ExcelReader { @Autowired private UserService userService; /** * 读取 Excel 表格中的数据,并将数据存储到数据库中 */ public void readExcel(String fileName) { EasyExcel.read(fileName, User.class, new UserExcelListener()).sheet().doRead(); } /** * 用户Excel监听器 */ private class UserExcelListener extends AnalysisEventListener<User> { /** * 每读取一行数据,就会调用该方法 */ @Override public void invoke(User user, AnalysisContext context) { userService.save(user); } /** * 读取完整个 Excel 表格后,会调用该方法 */ @Override public void doAfterAllAnalysed(AnalysisContext context) { // do nothing } } } ``` 4. 创建Excel导出器 创建一个 Excel 导出器,用于从数据库中获取数据,并将数据导出到 Excel 表格中。 ```java @Component public class ExcelWriter { @Autowired private UserService userService; /** * 将用户数据导出到 Excel 表格中 */ public void writeExcel(String fileName) { List<User> userList = userService.list(); EasyExcel.write(fileName, User.class).sheet().doWrite(userList); } } ``` 5. 创建Controller 创建一个 Controller,用于接收前端请求,并调用相应的方法处理请求。 ```java @RestController @RequestMapping("/user") public class UserController { @Autowired private ExcelReader excelReader; @Autowired private ExcelWriter excelWriter; /** * 批量导入用户数据 */ @PostMapping("/import") public void importExcel(@RequestParam("file") MultipartFile file) throws IOException { excelReader.readExcel(file.getInputStream()); } /** * 导出用户数据Excel */ @GetMapping("/export") public void exportExcel(HttpServletResponse response) throws IOException { String fileName = "用户信息.xlsx"; response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); response.setContentType("application/vnd.ms-excel"); excelWriter.writeExcel(response.getOutputStream()); } } ``` 6. 配置文件 在 application.yml 文件中添加数据库连接信息。 ```yaml spring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai username: root password: root mybatis-plus: mapper-locations: classpath:/mapper/*.xml type-aliases-package: com.example.demo.domain ``` 7. 测试 启动应用程序,并在浏览器中访问以下地址: - http://localhost:8080/user/export :导出 Excel 表格 - http://localhost:8080/user/import :导入 Excel 表格 以上就是 SpringBoot+Mybatis-plus整合easyExcel批量导入Excel数据库+导出Excel 的方法了,希望能帮到你。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值