java怎么将excel导入到数据库
- 数据库
- 2025-08-04
- 1
Apache POI解析Excel文件,结合JDBC批量执行SQL插入
Java中将Excel文件导入数据库是一个常见的需求,通常涉及使用Apache POI库读取Excel数据,并通过JDBC连接数据库进行插入操作,以下是详细的实现步骤和示例代码:
准备工作
-
环境配置
- 确保已安装Java JDK(建议版本≥8)、IDE工具(如IntelliJ IDEA或Eclipse),以及目标数据库管理系统(例如MySQL)。
- 如果使用Maven管理项目依赖,需在
pom.xml
中添加以下库:<!-Apache POI用于处理Excel --> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>5.2.3</version> </dependency> <!-MySQL驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.28</version> </dependency>
-
创建测试用的Excel文件:例如名为
data.xlsx
的文件,内容包含表头和若干行记录,示例结构如下:
| ID | Name | Age |
|—-|———|—–|
| 1 | Alice | 30 |
| 2 | Bob | 25 | -
设计数据库表结构:根据Excel的列名创建对应的数据库表,在MySQL中执行:
CREATE TABLE users ( id INT PRIMARY KEY, name VARCHAR(255), age INT );
核心实现步骤
读取Excel文件
使用Apache POI解析Excel文件,逐行提取数据,关键点包括:跳过表头行、处理不同类型单元格(字符串/数字等)、避免空值异常,以下是典型代码片段:
import org.apache.poi.ss.usermodel.; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.FileInputStream; import java.util.ArrayList; import java.util.List; public class ExcelReader { public List<List<Object>> readExcel(String filePath) throws IOException { List<List<Object>> dataList = new ArrayList<>(); try (FileInputStream fis = new FileInputStream(filePath); Workbook workbook = new XSSFWorkbook(fis)) { Sheet sheet = workbook.getSheetAt(0); // 获取第一个工作表 for (Row row : sheet) { if (row.getRowNum() == 0) continue; // 跳过表头 List<Object> rowData = new ArrayList<>(); for (Cell cell : row) { switch (cell.getCellType()) { case STRING: rowData.add(cell.getStringCellValue()); break; case NUMERIC: rowData.add(cell.getNumericCellValue()); break; default: rowData.add(null); // 其他类型暂存为null } } dataList.add(rowData); } } return dataList; } }
注意:上述代码通过判断单元格类型动态适配不同格式的数据,确保数值型字段不会被错误转换为字符串。
连接数据库并插入数据
通过JDBC建立连接后,利用PreparedStatement
批量执行SQL语句以提高效率,推荐使用事务管理保证操作的原子性:
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.List; public class DatabaseInserter { private static final String URL = "jdbc:mysql://localhost:3306/your_database"; private static final String USERNAME = "your_username"; private static final String PASSWORD = "your_password"; public void insertData(List<List<Object>> rows) throws SQLException { try (Connection conn = DriverManager.getConnection(URL, USERNAME, PASSWORD)) { String sql = "INSERT INTO users (id, name, age) VALUES (?, ?, ?)"; try (PreparedStatement pstmt = conn.prepareStatement(sql)) { for (List<Object> row : rows) { pstmt.setInt(1, (Integer) row.get(0)); // ID列为整数类型 pstmt.setString(2, (String) row.get(1)); // Name列为字符串类型 pstmt.setInt(3, (Integer) row.get(2)); // Age列为整数类型 pstmt.addBatch(); // 添加到批处理队列 } pstmt.executeBatch(); // 一次性执行所有批次操作 } } } }
优化点:①使用批处理(Batch Processing)减少网络交互次数;②显式指定参数类型防止SQL注入攻击;③自动提交事务由JDBC默认机制控制。
整合流程
将上述模块组合成完整的导入程序:
public class MainApp { public static void main(String[] args) { String excelPath = "src/main/resources/data.xlsx"; ExcelReader reader = new ExcelReader(); DatabaseInserter inserter = new DatabaseInserter(); try { List<List<Object>> rows = reader.readExcel(excelPath); inserter.insertData(rows); System.out.println("成功导入" + rows.size() + "条记录!"); } catch (Exception e) { e.printStackTrace(); } } }
常见问题与解决方案
序号 | 问题描述 | 解决方法 |
---|---|---|
1 | Excel日期格式解析失败 | 改用DateUtil.isCellDateFormatted() 检测后,通过DateUtil.getJavaDate() 转换 |
2 | 大数据量导致内存溢出 | 分块读取Excel(使用SXSSFWorkbook 流式API),限制单次加载行列数 |
3 | 字符编码乱码 | 确保数据库连接URL添加参数useUnicode=true&characterEncoding=UTF-8 |
4 | 主键冲突或唯一约束违反 | 插入前先查询是否存在相同记录,或启用数据库的ON DUPLICATE KEY UPDATE机制 |
相关问答FAQs
Q1: 如果Excel中有合并单元格怎么办?
A: 合并单元格在POI中会被视为普通单元格,但其内容仅存储于首个合并区域的锚点位置,可通过sheet.getMergeRegions()
获取所有合并区域信息,手动填充缺失的值。
for (int i = 0; i < sheet.getNumMergedRegions(); i++) { CellRangeAddress region = sheet.getMergedRegion(i); // 根据业务逻辑处理跨行合并的情况 }
Q2: 如何提高导入速度?
A: 除批处理外,还可采取以下措施:①禁用索引后再导入(适用于MyISAM引擎);②调整数据库事务隔离级别为READ_UNCOMMITTED
;③多线程并行处理不同Sheet;④关闭自动提交(conn.setAutoCommit(false)
),手动分阶段提交事务