JDBC链接数据库查询1000万数据并导出execl表格使用多线程和深度分页

本文介绍了如何使用SpringBoot和EasyExcel框架异步从数据库批量导出数据到Excel文件,包括线程池、批量处理和性能优化策略。
摘要由CSDN通过智能技术生成

可以连接本地和服务器,本地更快一些,和电脑的性能也有关系

导入依赖

     <!-- easyExcel依赖-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.2.3</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-test</artifactId>
        </dependency>

编写自己的实体类

示例代码

@SpringBootTest
class TextApplicationTests {

    // 线程池大小
    private static final int THREAD_POOL_SIZE = 16;
    // 批量处理数据大小
    private static final int BATCH_SIZE = 625000;
    // 全局表格索引,使用AtomicInteger保证线程安全递增
    private static final AtomicInteger globalSheetIndex = new AtomicInteger(0);
    // 同步锁
    private static final Object lock = new Object();

    public static void main(String[] args) {
        // 数据库连接信息
        String jdbcUrl = "jdbc:mysql://服务器或者本地:3306/你的数据库";
        String username = "";
        String password = "";
        // 导出文件路径
        String outputPath = "D:\\sss.xlsx";

        // 记录开始时间
        long startTime = System.currentTimeMillis();

        // 创建一个 ExcelWriter 对象
        ExcelWriter excelWriter = EasyExcel.write(outputPath).excelType(ExcelTypeEnum.XLSX).build();

        // 异步方式从数据库导出数据到 Excel 文件
        exportData(jdbcUrl, username, password, excelWriter);

        // 关闭 ExcelWriter 对象
        excelWriter.finish();

        // 记录结束时间
        long endTime = System.currentTimeMillis();
        // 计算执行时间
        long duration = endTime - startTime;
        // 打印导出耗时
        System.out.println("导出耗时:" + duration + " 毫秒");
    }


    // 导出数据方法
    private static void exportData(String jdbcUrl, String username, String password, ExcelWriter excelWriter) {
        try (Connection connection = DriverManager.getConnection(jdbcUrl, username, password)) {
            // 获取总行数
            int rowCount = getTotalRowCount(connection);
            int pageSize = BATCH_SIZE;

            try {
                CountDownLatch latch = new CountDownLatch(THREAD_POOL_SIZE);
                ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE);

                // 分批次处理数据
                for (int i = 0; i < rowCount; i += pageSize) {
                    int endIndex = Math.min(i + pageSize, rowCount);
                    List<People> subList = fetchData(connection, i, endIndex);


                    executorService.submit(() -> {
                        synchronized (lock) {

                        WriteSheet writeSheet = EasyExcel.writerSheet(globalSheetIndex.getAndIncrement(), "sheet" + globalSheetIndex).build();
                        writeToExcel(excelWriter, subList, writeSheet);
                        }
                        latch.countDown();
                    });
                }

                // 关闭线程池
                try {
                    latch.await(); // 等待所有线程完成
                    executorService.shutdown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                // 关闭 ExcelWriter 对象
                excelWriter.finish();

            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    // 获取总行数方法
    private static int getTotalRowCount(Connection connection) throws SQLException {
        // 创建统计语句对象,准备查询people表中的记录数
        try (PreparedStatement countStatement = connection.prepareStatement("SELECT COUNT(*) FROM people");
             // 执行统计语句并获取查询结果集
             ResultSet countResultSet = countStatement.executeQuery()) {
            // 从结果集中获取计数信息
            countResultSet.next();
            // 返回记录数
            return countResultSet.getInt(1);
        }
    }


    // 获取分批次数据方法
    private static List<People> fetchData(Connection connection, int startIndex, int endIndex) {
        List<People> dataList = new ArrayList<>();
        try (PreparedStatement dataStatement = connection.prepareStatement("SELECT * FROM people LIMIT ?, ?")) {
            // 设置参数
            dataStatement.setInt(1, startIndex);
            dataStatement.setInt(2, endIndex - startIndex);
            ResultSet resultSet = dataStatement.executeQuery();

            // 遍历结果集
            while (resultSet.next()) {
                People people = new People();
                // 获取数据并设置给people对象的属性
                people.setId(resultSet.getInt("id"));
                people.setName(resultSet.getString("name"));
                people.setAge(resultSet.getInt("age"));
                people.setSex(resultSet.getInt("sex"));
                people.setPhone(resultSet.getString("phone"));
                people.setDescribe(resultSet.getString("describe"));
                people.setStatus(resultSet.getString("status"));
                people.setDeleted(resultSet.getInt("deleted"));
                people.setUpdateTime(resultSet.getString("update_time"));
                people.setUpdater(resultSet.getString("updater"));
                dataList.add(people);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return dataList;
    }


    // 写入 Excel 方法
    private static void writeToExcel(ExcelWriter excelWriter, List<People> dataList, WriteSheet writeSheet) {

        try {
            // 累积一定数量的数据再写入
            int batchSize = 1000000;
            for (int i = 0; i < dataList.size(); i += batchSize) {
                int endIndex = Math.min(i + batchSize, dataList.size());
                List<People> subList = dataList.subList(i, endIndex);
                excelWriter.write(subList, writeSheet);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }




}

在Java中,我们可以使用Apache POI库来实现从数据库(如MySQL、Oracle等)读取数据并写入Excel文件的功能。以下是一个简化的步骤概述: 1. **添加依赖**: 首先,需要在项目中引入Apache POI的相关组件,包括`poi`, `poi-ooxml`, 和 `sqljdbc` (用于JDBC操作数据库)。 ```java <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>latest version</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>latest version</version> </dependency> <dependency> <groupId>com.microsoft.sqlserver</groupId> <artifactId>mssql-jdbc</artifactId> <version>latest version</version> </dependency> ``` 2. **数据库连接**: 使用JDBC连接数据库,获取查询结果集(ResultSet)。 ```java String url = "jdbc:sqlserver://localhost:1433;databaseName=your_database"; String user = "your_username"; String password = "your_password"; Connection connection = DriverManager.getConnection(url, user, password); Statement statement = connection.createStatement(); String sql = "SELECT * FROM your_table"; ResultSet resultSet = statement.executeQuery(sql); ``` 3. **创建Excel工作簿**: 使用`HSSFWorkbook`或`XSSFWorkbook`(对于xlsx格式)创建一个新的Excel工作簿,并选择一个工作表。 ```java Workbook workbook; if (/* 根据需求选择HSSF或XSSF */) { workbook = new HSSFWorkbook(); } else { workbook = new XSSFWorkbook(); } Sheet sheet = workbook.createSheet("Your Sheet Name"); Row headerRow = sheet.createRow(0); // 创建表头行 headerRow.createCell(0).setCellValue("Column1"); // 添加其他列... ``` 4. **处理数据**: 遍历数据库的结果集,将每一行的数据写入Excel表格。 ```java while (resultSet.next()) { Row dataRow = sheet.createRow(resultSet.getRowNum() + 1); for (int i = 1; i <= resultSet.getMetaData().getColumnCount(); i++) { dataRow.createCell(i - 1).setCellValue(resultSet.getObject(i)); } } ``` 5. **保存Excel文件**: 最后关闭连接、工作簿以及相关的资源,并将文件写入磁盘。 ```java workbook.write(new File("output.xlsx")); workbook.close(); connection.close(); ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值