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

使用 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
}
}
注意事项
- 内存管理:对于大文件,建议使用监听器方式(如EasyExcel)而不是一次性读取到内存
- 数据验证:导入前应对数据进行验证,确保符合业务规则
- 事务处理:批量导入通常需要事务支持,确保数据一致性
- 错误处理:记录导入过程中的错误,方便后续处理
- 性能优化:可以考虑多线程处理或分批次导入以提高性能
其他工具
除了上述方法,还可以考虑:

- JXL (较老,不再推荐)
- OpenCSV (适合CSV文件)
- Apache Commons CSV (轻量级CSV处理)
选择哪种方法取决于你的具体需求、文件大小和性能要求,对于现代Java项目,EasyExcel通常是首选,因为它性能好且内存占用低。
