一、需求描述
Excel表格里面大约有20个sheet页,每个sheet页65535条数据,需要读取全部数据,并导入至数据库。
找了好多种方式,EasyExcel比较符合,下面看代码。
二、实现方式 采用EasyExcel框架的doReadAll()方法
1、DemoController
/**
* 导入文件分析
*/
public void importAll()
{
String fileName = "D:\\aa.xlsx";
//读取所有Sheet的数据.每次读完一个Sheet就会调用这个方法
EasyExcel.read(fileName, new EasyExceGeneralDatalListener(empService)).doReadAll();
}
2、EmpService
import java.util.List;
import java.util.Map;
public interface EmpService
{
public void importData(List<Map<Integer, String>> dataList);
}
3、EmpServiceImpl
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Service;
import com.ruoyi.imp.service.EmpService;
import com.ruoyi.jdbc.util.JDBCDruidUtils;
@Service
public class EmpServiceImpl implements EmpService
{
/*
* 测试用Excel导入超过10w条数据,经过测试发现,使用Mybatis的批量插入速度非常慢,所以这里可以使用 数据分批+JDBC分批插入+事务来继续插入速度会非常快
*/
@Override
public void importData(List<Map<Integer, String>> dataList) {
//结果集中数据为0时,结束方法.进行下一次调用
if (dataList.size() == 0) {
return;
}
//JDBC分批插入+事务操作完成对20w数据的插入
Connection conn = null;
PreparedStatement ps = null;
try {
long startTime = System.currentTimeMillis();
System.out.println("此次共"+dataList.size() + "条数据,导入开始时间:" + startTime + "ms");
// JDBCDruidUtils.getConnection() 此部分为JDBC连接,百度一下就有
conn = JDBCDruidUtils.getConnection();
//控制事务:默认不提交
conn.setAutoCommit(false);
String sql = "insert into tp_import_all (wy,kh,ch,dk,on,wlc,ncv,mc,jmc) values";
sql += "(?,?,?,?,?,?,?,?,?)";
ps = conn.prepareStatement(sql);
//循环结果集:这里循环不支持"烂布袋"表达式
for (int i = 0; i < dataList.size(); i++) {
Map<Integer, String> item = dataList.get(i);
ps.setString(1, item.get(0));
ps.setString(2, item.get(1));
ps.setString(3, item.get(2));
ps.setString(4, item.get(3));
ps.setString(5, item.get(4));
ps.setString(6, item.get(5));
ps.setString(7, item.get(6));
ps.setString(8, item.get(7));
ps.setString(9, item.get(8));
//将一组参数添加到此 PreparedStatement 对象的批处理命令中。
ps.addBatch();
}
System.out.println("importData方法,executeBatch()...开始执行");
//执行批处理
ps.executeBatch();
System.out.println("importData方法,executeBatch()...执行结束");
System.out.println("importData方法,commit()...开始提交");
//手动提交事务
conn.commit();
System.out.println("importData方法,commit()...提交结束");
long endTime = System.currentTimeMillis();
System.out.println(dataList.size() + "条,导入结束时间:" + endTime + "ms");
System.out.println("导入用时:" + (endTime - startTime) + "ms");
} catch (Exception e) {
e.printStackTrace();
System.out.println("catch Exception e");
} finally {
//关连接
JDBCDruidUtils.close(conn, ps);
System.out.println("JDBCDruidUtils.close 关连接");
}
}
}
4、EasyExceGeneralDatalListener
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.ruoyi.imp.service.EmpService;
// 事件监听
public class EasyExceGeneralDatalListener extends AnalysisEventListener<Map<Integer, String>> {
/**
* 处理业务逻辑的Service,也可以是Mapper
*/
private EmpService empService;
/**
* 用于存储读取的数据
*/
private List<Map<Integer, String>> dataList = new ArrayList<Map<Integer, String>>();
public EasyExceGeneralDatalListener() {
}
public EasyExceGeneralDatalListener(EmpService empService) {
this.empService = empService;
}
@Override
public void invoke(Map<Integer, String> data, AnalysisContext context) {
//数据add进入集合
dataList.add(data);
//size是否为100000条:这里其实就是分批.当数据等于20w的时候执行一次插入
if (dataList.size() >= ExcelConstants.GENERAL_ONCE_SAVE_TO_DB_ROWS) {//ExcelConstants.GENERAL_ONCE_SAVE_TO_DB_ROWS Integer类型,控制条数
//存入数据库:数据小于1w条使用Mybatis的批量插入即可;
saveData();
//清理集合便于GC回收
dataList.clear();
}
}
/**
* 保存数据到DB
*
* @param
* @MethodName: saveData
* @return: void
*/
private void saveData() {
System.out.println("saveData方法,importData...开始");
//
empService.importData(dataList);
System.out.println("saveData方法,importData...结束");
// 回收
dataList.clear();
}
/**
* Excel中所有数据解析完毕会调用此方法
*
* @param: context
* @MethodName: doAfterAllAnalysed
* @return: void
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
System.out.println("doAfterAllAnalysed方法,saveData...开始");
// 调用方法
saveData();
System.out.println("doAfterAllAnalysed方法,saveData...结束");
// 回收
dataList.clear();
}
}
三、其他问题
1、所用版本
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.2.10</version>
</dependency>
2、可能会碰到null的报错,可以检查下poi版本是否冲突,这边用的4.1的版本
如果出现poi-ooxml是4.x版本,poi是3.x 可能会出错