Excel导入性能优化

时间:2022-11-16 17:26:53

       需求:http://blog.csdn.net/u013036274/article/details/51848592继上次的导入Excel数据实现,但是导入的太慢。因为保存数据库之前需要查重,查询数据库的次数太多,有多少条数据就查询多少次数据库,导致导入数据越多,导入速度越慢,性能有待提高,于是乎,先从代码优化做起吧。

       思路:由于是学生信息的导入,学生的学号就是主键,而且学生的学号也是根据年份、学院、专业、班级等有规律的,所以如果要查询某学号是否存在,可以缩小范围到在一个班级内查重即可。所以先根据班级名称查询,合格的班级名称才可以进行下一步验证,再根据正确的班级名称查出对应的学号,对学号进行查重。合格的学号的学生信息则可以保存到数据库中。具体实现如下:

【controller】

/**
	 * @author -徐志鹏、郑艳霞
	 * @MethodName : importStudent
	 * @Description : 导入
	 * @throws Exception
	 */
	@RequestMapping(value = "/student/importStudent", method = RequestMethod.POST)
	public void importStudent(HttpServletResponse response,
			HttpServletRequest request) {
		// 动态获取数据库名称
		String dataBaseName = (String) request.getSession().getAttribute(
				CloudContext.DatabaseName)
				+ "_basic";
		// 创建一个通用的多部分解析器
		CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(
				request.getSession().getServletContext());
		InputStream inExcelFile = null;
		// 判断 request 是否有文件上传,即多部分请求importDailyResult
		if (multipartResolver.isMultipart(request)) {
			// 转换成多部分request
			MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;

			// 取得request中的所有文件名
			Iterator<String> iter = multiRequest.getFileNames();
			while (iter.hasNext()) {
				// 记录上传过程起始时的时间,用来计算上传时间
				int pre = (int) System.currentTimeMillis();
				// 取得上传文件
				MultipartFile file = multiRequest.getFile(iter.next());
				try {
					inExcelFile = file.getInputStream();
				} catch (IOException e) {
					e.printStackTrace();
				}

			}

		}

		// 创建一个list 用来存储读取的Excel的内容
		List<Student> excelStudentList = new ArrayList<Student>();
		// 创建一个list集合,保存无法导入的数据
		List<Student> errorStudentList = new ArrayList<Student>();

		String result = "error";

		try {
			excelStudentList = this.getExcelData(inExcelFile);

			if (excelStudentList == null && excelStudentList.size() < 0) {
				result = "error";
			} else {
				errorStudentList = studentBean.importExcel(dataBaseName,
						excelStudentList);
				if (errorStudentList == null) {
					result = "success";
				} else {
					result = "error";
					this.ExportExcel(errorStudentList);
				}
			}
		} catch (Exception e) {
			result = "error";
		}
		jacksonJsonUntil.beanToJson(response, result);
	}
/**
	 * 把输入流文件转变成list集合
	 * 
	 * @param inExcelFile
	 * @return
	 */
	public List<Student> getExcelData(InputStream inExcelFile) {
		// 创建一个list 用来存储读取的内容
		List<Student> list = new ArrayList<>(1);
		Workbook rwb = null;
		// 获取Excel文件对象
		try {
			rwb = Workbook.getWorkbook(inExcelFile);
		} catch (BiffException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		// 获取文件的指定工作表 默认的第一个
		Sheet sheet = rwb.getSheet(0);

		// 行数(表头的目录不需要,从1开始)
		System.out.println(sheet.getRows());
		for (int i = 1; i < sheet.getRows(); i++) {

			Student model = new Student();

			model.setCode(sheet.getCell(0, i).getContents()); // 第一列:学号
			model.setName(sheet.getCell(1, i).getContents()); // 第二列:姓名
			model.setSex(sheet.getCell(2, i).getContents()); // 第三列:性别
			model.setClassName(sheet.getCell(3, i).getContents()); // 第四列:班级名称
			model.setEntranceDate(sheet.getCell(4, i).getContents()); // 第五列:入学日期
			model.setIdentityCardID(sheet.getCell(5, i).getContents()); // 第六列:身份证号
			model.setNativePlaceNativePlace(sheet.getCell(6, i).getContents()); // 第七列:籍贯
			model.setNation(sheet.getCell(7, i).getContents()); // 第八列:民族
			model.setPoliticalStatus(sheet.getCell(8, i).getContents()); // 第九列:政治面貌
			model.setAccountAddress(sheet.getCell(9, i).getContents()); // 第十列:户口所在地
			model.setOriginalPlace(sheet.getCell(10, i).getContents()); // 第十一列:生源地
			model.setGraduatedSchool(sheet.getCell(11, i).getContents()); // 第十二列:毕业院校
			model.setEmail(sheet.getCell(12, i).getContents()); // 第十二列:电子邮箱
			model.setTelNum(sheet.getCell(13, i).getContents()); // 第十二列:手机

			// 把刚获取的列存入list
			list.add(model);
		}

		return list;
	}

	/**
	 * 将导入失败的数据导出至Excel表--郑艳霞--2016年8月2日16:22:38-v5.0
	 * 
	 * @param studentList
	 */
	@SuppressWarnings("deprecation")
	public void ExportExcel(List<Student> studentList) {
		// 第一步,创建一个webbook,对应一个Excel文件
		@SuppressWarnings("resource")
		HSSFWorkbook wb = new HSSFWorkbook();
		// 第二步,在webbook中添加一个sheet,对应Excel文件中的sheet
		HSSFSheet sheet = wb.createSheet("导入失败的学生");
		// 第三步,在sheet中添加表头第0行,注意老版本poi对Excel的行数列数有限制short
		HSSFRow row = sheet.createRow((int) 0);
		// 第四步,创建单元格,并设置值表头 设置表头居中
		HSSFCellStyle style = wb.createCellStyle();
		style.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 创建一个居中格式

		HSSFCell cell = row.createCell((short) 0);
		cell.setCellValue("学号");
		cell.setCellStyle(style);

		cell = row.createCell((short) 1);
		cell.setCellValue("姓名");
		cell.setCellStyle(style);

		cell = row.createCell((short) 2);
		cell.setCellValue("性别");
		cell.setCellStyle(style);

		cell = row.createCell((short) 3);
		cell.setCellValue("所属班级");
		cell.setCellStyle(style);

		cell = row.createCell((short) 4);
		cell.setCellValue("入学日期");
		cell.setCellStyle(style);

		cell = row.createCell((short) 5);
		cell.setCellValue("身份证号");
		cell.setCellStyle(style);

		cell = row.createCell((short) 6);
		cell.setCellValue("籍贯");
		cell.setCellStyle(style);

		cell = row.createCell((short) 7);
		cell.setCellValue("民族");
		cell.setCellStyle(style);

		cell = row.createCell((short) 8);
		cell.setCellValue("政治面貌");
		cell.setCellStyle(style);

		cell = row.createCell((short) 9);
		cell.setCellValue("户口所在地");
		cell.setCellStyle(style);

		cell = row.createCell((short) 10);
		cell.setCellValue("生源地");
		cell.setCellStyle(style);

		cell = row.createCell((short) 11);
		cell.setCellValue("毕业学校");
		cell.setCellStyle(style);

		cell = row.createCell((short) 12);
		cell.setCellValue("电子邮箱");
		cell.setCellStyle(style);

		cell = row.createCell((short) 13);
		cell.setCellValue("手机");
		cell.setCellStyle(style);
		// 第五步,写入实体数据 实际应用中这些数据从数据库得到,

		for (int i = 0; i < studentList.size(); i++) {
			row = sheet.createRow((int) i + 1);
			Student student = (Student) studentList.get(i);
			// 第四步,创建单元格,并设置值
			row.createCell((short) 0).setCellValue(student.getCode());
			row.createCell((short) 1).setCellValue(student.getName());
			row.createCell((short) 2).setCellValue(student.getSex());
			row.createCell((short) 3).setCellValue(student.getClassName());
			row.createCell((short) 4).setCellValue(student.getEntranceDate());
			row.createCell((short) 5).setCellValue(student.getIdentityCardID());
			row.createCell((short) 6).setCellValue(
					student.getNativePlaceNativePlace());
			row.createCell((short) 7).setCellValue(student.getNation());
			row.createCell((short) 8)
					.setCellValue(student.getPoliticalStatus());
			row.createCell((short) 9).setCellValue(student.getAccountAddress());
			row.createCell((short) 10).setCellValue(student.getOriginalPlace());
			row.createCell((short) 11).setCellValue(
					student.getGraduatedSchool());
			row.createCell((short) 12).setCellValue(student.getEmail());
			row.createCell((short) 13).setCellValue(student.getTelNum());
		}
		// 第六步,将文件存到指定位置
		try {
			FileSystemView fsv = FileSystemView.getFileSystemView();

			Date currentTime = new Date();
			SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddhhmmss");
			String dateString = formatter.format(currentTime);
			String deskPath = fsv.getHomeDirectory().toString() + "/导入失败的学生数据"
					+ dateString + ".xls";
			FileOutputStream fout = new FileOutputStream(deskPath);

			wb.write(fout);
			fout.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

【StudentBeanImpl】

	/**
	 * 导入学生--郑艳霞-2016年8月2日15:44:48-v5.0
	 * 
	 * @param dataBaseName
	 * @param studentList
	 * @return
	 */
	@Override
	public List<Student> importExcel(String dataBaseName,
			List<Student> excelList) {
		// 创建一个list集合,保存无法导入的数据
		List<Student> errorStudentList = new ArrayList<Student>();
		// 创建一个list集合,保存可以导入的数据
		List<Student> studentList = new ArrayList<Student>();
		List<Student> Nonlist = new ArrayList<Student>();
		Nonlist.add(null);

		// 创建一个集合,保存班级名称
		List<Classes> classNameList = new ArrayList<Classes>();
		Classes classes = new Classes();
		// for循环获取班级名称,存入List<Classes> classNameList
		for (int i = 0; i < excelList.size(); i++) {
			classes.setClassName(excelList.get(i).getClassName());
			classNameList.add(classes);
		}
		// 根据班级名称查询班级信息(classId和className)
		List<Classes> classIdAndNameList = studentEao
				.queryClassInfoByClassNameList(classNameList, dataBaseName);

		// 创建一个集合,保存classId
		List<Student> classIdsList = new ArrayList<Student>();
		Classes classEntity = new Classes();

		// 6.判断查询出来班级名称classidList和导入的班级名称是否有相同,
		// 如果有再进行第7步,没有则将对应信息添加到errorList

		for (int j = 0; j < excelList.size(); j++) {
			for (int s = 0; s < classIdAndNameList.size(); s++) {
				if (excelList
						.get(j)
						.getClassName()
						.toString()
						.equals(classIdAndNameList.get(s).getClassName()
								.toString())) {
					// 如果班级名称相同,则从查出来的数据中取出班级Id放入excelList中的classesId中
					excelList.get(j).setClassesId(
							classIdAndNameList.get(s).getId().toString());
					break;
				}
			}
			// 7.如果导入数据的班级名称与查询出来的班级名称没有相同的,则将数据加入到errorStudentList中
			if (excelList.get(j).getClassesId() == null) {
				errorStudentList.add(excelList.get(j));
				excelList.remove(j);
				excelList.removeAll(Nonlist);
				j = j - 1;
			}
		}
		// 9.根据班级Id的list查询班级Id和学生code
		List<Student> studentCodeAndClassIdList = studentEao
				.queryStudentCodeByClassesIdList(excelList, dataBaseName);

		for (int j = 0; j < excelList.size(); j++) {
			for (int s = 0; s < studentCodeAndClassIdList.size(); s++) {
				System.out.println(excelList.get(j).getCode().toString());
				System.out.println(studentCodeAndClassIdList.get(s).getCode()
						.toString());
				if (excelList
						.get(j)
						.getCode()
						.toString()
						.equals(studentCodeAndClassIdList.get(s).getCode()
								.toString())) {
					errorStudentList.add(excelList.get(j));
					excelList.remove(j);
					excelList.removeAll(Nonlist);
					break;
				}

			}
			j = j - 1;
		}

		// 10.遍历要导入的数据,并将数据add到studentlist中
		Student student = new Student();
		for (int i = 0; i < excelList.size(); i++) {
			String classesId = excelList.get(i).getClassesId();
			// 3.将该条信息添加到学生实体中
			// 将学生信息添加进studentList中--start
			String id = CreateUUID22.getUUID22();
			student.setId(id);
			student.setCode(excelList.get(i).getCode());
			student.setName(excelList.get(i).getName());
			student.setSex(excelList.get(i).getSex());
			student.setClassesId(classesId);
			student.setEntranceDate(excelList.get(i).getEntranceDate());
			student.setIdentityCardID(excelList.get(i).getIdentityCardID());
			student.setNativePlaceNativePlace(excelList.get(i)
					.getNativePlaceNativePlace());
			student.setNation(excelList.get(i).getNation());
			student.setPoliticalStatus(excelList.get(i).getPoliticalStatus());
			student.setAccountAddress(excelList.get(i).getAccountAddress());
			student.setOriginalPlace(excelList.get(i).getOriginalPlace());
			student.setGraduatedSchool(excelList.get(i).getGraduatedSchool());
			student.setEmail(excelList.get(i).getEmail());
			student.setTelNum(excelList.get(i).getTelNum());
			student.setDataBaseName(dataBaseName);
			studentList.add(student);
			// 将学生信息添加进studentList中--end
		}

		// 将学生信息导入到数据库-start
		if (studentList.size() > 0) {
			this.saveEntitys(studentList);
		}
		// 将学生信息导入到数据库-end
		return errorStudentList;
	}


        其他代码不在赘述。感谢红霞霞的指导O(∩_∩)O哈哈~

        功能的实现肯定小菜一碟,只要思路清晰每个开发都可以实现,但是我们要做的是高效简便的实现,性能就是第一要解决的问题,从代码上进行优化,让我们的程序简洁明了高效。做一个高效的人,从代码开始!

                                             Excel导入性能优化