环境:mysql5.7.28 java8 Spring boot 2.2.4 mybatis-plus3.10
动态:根据需求,用户可以选择对应的字段生成excle模版 下载
poi 反射:poi是excel的第三方jar,反射的作用是给表实体对象属性赋值,方便入库操作。
现在很多的应用都有批量导入的功能,批量导入用的最多的也是excel。我们实际的项目中也用了很多这方面的功能,所以博主系统的CV了一下这方面的代码,下面分步骤进行该功能的实现。此方法的优点:不限于模版字段的排列顺序,避免过多的重复set代码。动态的生成模版信息。
注意:数据库实体类属性变量名,要严格按照驼峰的模式命名,方便数据的读取,反射的赋值。
如果数据量过大,建议采用多线程的方式导入数据,数据的分割根据实际情况,本文采用的是单线程方式执行。
1:依赖的jar包
org.apache.poi
poi-ooxml
3.17
org.apache.poi
poi
3.17
commons-io
commons-io
2.4
2:生成对应数据库的模版
生成模版的前提是查询数据库有哪些字段,有了字段的信息,就可以根据java se中的流知识,生成对应的模版文件,下面的这个是查询表结构的所有信息。因为是要生成字段对应的模版,所以我们把sql修改一下即可select * from information_schema.COLUMNS where table_name = '表名'
查询字段的sql如下:select COLUMN_NAME from information_schema.COLUMNS where table_name = '表名'
同样的这个查询也可以用mybatis框架进行映射,返回的是List 类型,对应的mapper层次如下。List queryColumn();
到这步,我们的字段信息就有了,也就是excel的表头信息有了,下面就是根据表头信息生成对应的模版了。
生成代码如下图:需要说明的是传入的参数:数据库的字段信息,模版的名称(可任意取),生成模版的路径所在地
public static boolean createModel(List list, String modelName, String modelPath) {
boolean newFile = false;
//创建excel工作簿
HSSFWorkbook workbook = new HSSFWorkbook();
//创建工作表sheet
HSSFSheet sheet = workbook.createSheet();
//创建第一行
HSSFRow row = sheet.createRow(0);
HSSFCell cell;
//设置样式
CellStyle style = workbook.createCellStyle();
style.setFillForegroundColor(IndexedColors.AQUA.getIndex());
//插入第一行数据的表头
for (int i = 0; i < list.size(); i ) {
cell = row.createCell(i);
cell.setCellStyle(style);
cell.setCellValue(list.get(i));
}
//创建excel文件
File file = new File(modelPath File.separator modelName);
try {
//删除该文件夹下原来的模版文件
deleteDir(new File(modelPath File.separator));
//判断对应的文件夹是否有,无则新建
File myPath = new File(modelPath);
if (!myPath.exists()) {
myPath.mkdir();
}
//创建新的模版文件
newFile = file.createNewFile();
//将excel写入
FileOutputStream stream = FileUtils.openOutputStream(file);
workbook.write(stream);
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
return newFile;
}
下面的是删除原来模版文件的工具方法private static boolean deleteDir(File dir) {
if (dir.isDirectory()) {
String[] children = dir.list();
if (children != null)
//递归删除目录中的子目录下
for (String child : children) {
boolean success = deleteDir(new File(dir, child));
if (!success) {
return false;
}
}
}
// 目录此时为空,可以删除
return dir.delete();
}</