杰瑞科技汇

Java批量导入Excel,如何高效实现?

Java 批量导入 Excel 数据

在 Java 中批量导入 Excel 数据是一个常见的需求,通常用于数据迁移、批量录入等场景,下面我将介绍几种常用的实现方法。

Java批量导入Excel,如何高效实现?-图1
(图片来源网络,侵删)

使用 Apache POI

Apache POI 是最常用的 Java 操作 Office 文件的库,支持 Excel 的读写。

Maven 依赖

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>5.2.3</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>5.2.3</version>
</dependency>

示例代码

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class ExcelImportExample {
    public static List<List<String>> readExcel(String filePath) throws IOException {
        List<List<String>> data = new ArrayList<>();
        try (FileInputStream fis = new FileInputStream(filePath);
             Workbook workbook = new XSSFWorkbook(fis)) {
            Sheet sheet = workbook.getSheetAt(0); // 获取第一个工作表
            for (Row row : sheet) {
                List<String> rowData = new ArrayList<>();
                for (Cell cell : row) {
                    switch (cell.getCellType()) {
                        case STRING:
                            rowData.add(cell.getStringCellValue());
                            break;
                        case NUMERIC:
                            if (DateUtil.isCellDateFormatted(cell)) {
                                rowData.add(cell.getDateCellValue().toString());
                            } else {
                                rowData.add(String.valueOf(cell.getNumericCellValue()));
                            }
                            break;
                        case BOOLEAN:
                            rowData.add(String.valueOf(cell.getBooleanCellValue()));
                            break;
                        case FORMULA:
                            rowData.add(cell.getCellFormula());
                            break;
                        default:
                            rowData.add("");
                    }
                }
                data.add(rowData);
            }
        }
        return data;
    }
    public static void main(String[] args) {
        try {
            List<List<String>> excelData = readExcel("path/to/your/file.xlsx");
            // 处理导入的数据
            for (List<String> row : excelData) {
                System.out.println(row);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

使用 EasyExcel

EasyExcel 是阿里巴巴开源的 Excel 处理工具,性能更好,内存占用更少。

Maven 依赖

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

示例代码

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import java.util.ArrayList;
import java.util.List;
public class EasyExcelExample {
    public static void main(String[] args) {
        String fileName = "path/to/your/file.xlsx";
        // 方式1:简单读取
        List<List<String>> data = EasyExcel.read(fileName)
                .sheet()
                .doReadSync();
        // 方式2:使用监听器(推荐,内存更友好)
        List<DataModel> dataList = new ArrayList<>();
        EasyExcel.read(fileName, DataModel.class, new AnalysisEventListener<DataModel>() {
            @Override
            public void invoke(DataModel data, AnalysisContext context) {
                dataList.add(data);
            }
            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                // 所有数据解析完成
            }
        }).sheet().doRead();
    }
    // 定义数据模型
    public static class DataModel {
        @ExcelProperty("姓名")
        private String name;
        @ExcelProperty("年龄")
        private Integer age;
        @ExcelProperty("邮箱")
        private String email;
        // getters and setters
    }
}

批量导入到数据库

将 Excel 数据批量导入数据库的完整示例:

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class BatchImportToDatabase {
    private final JdbcTemplate jdbcTemplate;
    public BatchImportToDatabase(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
    public void importFromExcel(String filePath) {
        List<User> userList = new ArrayList<>();
        EasyExcel.read(filePath, User.class, new AnalysisEventListener<User>() {
            @Override
            public void invoke(User user, AnalysisContext context) {
                userList.add(user);
                // 每达到1000条数据就存储一次,防止内存溢出
                if (userList.size() >= 1000) {
                    saveData();
                    userList.clear();
                }
            }
            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                // 存储剩余数据
                saveData();
            }
            private void saveData() {
                jdbcTemplate.batchUpdate("INSERT INTO user(name, age, email) VALUES (?, ?, ?)",
                        new BatchPreparedStatementSetter() {
                            @Override
                            public void setValues(PreparedStatement ps, int i) throws SQLException {
                                User user = userList.get(i);
                                ps.setString(1, user.getName());
                                ps.setInt(2, user.getAge());
                                ps.setString(3, user.getEmail());
                            }
                            @Override
                            public int getBatchSize() {
                                return userList.size();
                            }
                        });
            }
        }).sheet().doRead();
    }
    public static class User {
        @ExcelProperty("姓名")
        private String name;
        @ExcelProperty("年龄")
        private Integer age;
        @ExcelProperty("邮箱")
        private String email;
        // getters and setters
    }
}

注意事项

  1. 内存管理:对于大文件,建议使用监听器方式(如EasyExcel)而不是一次性读取到内存
  2. 数据验证:导入前应对数据进行验证,确保符合业务规则
  3. 事务处理:批量导入通常需要事务支持,确保数据一致性
  4. 错误处理:记录导入过程中的错误,方便后续处理
  5. 性能优化:可以考虑多线程处理或分批次导入以提高性能

其他工具

除了上述方法,还可以考虑:

Java批量导入Excel,如何高效实现?-图2
(图片来源网络,侵删)
  • JXL (较老,不再推荐)
  • OpenCSV (适合CSV文件)
  • Apache Commons CSV (轻量级CSV处理)

选择哪种方法取决于你的具体需求、文件大小和性能要求,对于现代Java项目,EasyExcel通常是首选,因为它性能好且内存占用低。

分享:
扫描分享到社交APP
上一篇
下一篇