Java POI 多线程导入导出

1.多线程的导入导出。

导出的话是用JAVA POI excel导出,其中遇到的问题有两点。
其一:大量数据的导出
解决方案:用SXSSFWorkbook新excel可以导出超过6.5w条数据,而用03版的excel只能导出低于6.5w条的数据
其二:导出速度慢
解决方案:用分页和多线程的思想解决

1.Java Controller层,与前端对接

/**
 * @函数名称:export Control层
* @创建日期:2018年9月10日
* @功能说明:导出
* @参数说明:
* @返回说明:ModelAndView */
@RequestMapping("/export/{nti}") public ModelAndView export(HttpServletRequest request, HttpServletResponse response, AwbQueryNewQ querys, @PathVariable("nti") Integer nti) { response.setContentType("application/vnd.ms-excel"); response.setCharacterEncoding("UTF-8"); //获取当前登录的账号信息 UserAccount account = (UserAccount) SecurityUtils.getSubject().getPrincipal(); try { // 查询所有操作日志 List<AwbInfo> awbInfos = awbQueryNewService.findAllV2(querys.getNumPerPage(), querys.getPageNum(), null, generateWhere(querys), generateOrders(querys),account); awbInfos = flightRoute2CH(awbInfos); // 进行转码,使其支持中文文件名 awbQueryNewService.export(nti, awbInfos, request, response, querys.getOperDateBeginQ(), querys.getOperDateEndQ()); return null; } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); return ajaxDoneError("下载失败,如有问题请联系管理员"); } }

2.service层中多线程导出
其中start,end用到分页的思想

/**
 * 
 * @功能说明:查询运单表线程
 * @创建人员:HjwJames
 * @变更记录:
* 1、2019年9月11日 HjwJames 新建类 */
class Task implements Callable<List<AwbInfo>> { Integer start; Integer end; List<String> fields; List<Where> wheres; List<Order> orders; UserAccount account; Task(Integer start, Integer end, List<String> fields, List<Where> wheres, List<Order> orders, UserAccount account) { this.start = start; this.end = end; this.fields = fields; this.wheres = wheres; this.orders = orders; this.account = account; } @Override public List<AwbInfo> call() throws Exception { List<AwbInfo> list = null; try { list = awbInfoDao.getAwbInfosV2(start, end, fields, wheres, orders, account); } catch (Exception e) { e.printStackTrace(); } return list; } }

3.启动多线程,3000条数据/线程。
其中用到了callable和future和线程池,最后排序

/**
 * 
 * @函数名称:findAllV2
 * @创建日期:2019年9月17日
 * @author HjwJames
 * @功能说明:运单查询多线程导出
 * @参数说明:
 * @返回说明:List
 */
@Override
@TargetDataSource(name = "cargo_market_slave")
public List<AwbInfo> findAllV2(int numPerPage, int pageNum, List<String> fields, List<Where> wheres, List<Order> orders, UserAccount account)
		throws Exception {
	// 数据总数
	Integer total = awbInfoDao.getAwbInfosTotal(wheres, orders, account);
	// 分页数
	Integer num = 3000;
	// 结果集合
	List<AwbInfo> result = new ArrayList<>();
	// 需要查询的次数
	int times = total / num;
	if (total % num != 0) {
		times = times + 1;
	}
	// Callable用于产生结果
	List<Callable<List<AwbInfo>>> tasks = new ArrayList<>();
	Integer start = 0;
	Integer end = total < num ? total : num;
	for (int i = 0; i < times; i++) {
		Callable<List<AwbInfo>> task = new Task(start, end, fields, wheres, orders, account);
		tasks.add(task);
		start = num * (i + 1);
		end = num;
	}
	// 定义固定长度的线程池 防止线程过多
	ExecutorService executorService = Executors.newFixedThreadPool(15);
	// Future用于获取结果
	List<Future<List<AwbInfo>>> futures = executorService.invokeAll(tasks);
	// 处理线程返回结果
	if (futures != null && futures.size() > 0) {
		for (Future<List<AwbInfo>> future : futures) {
			result.addAll(future.get());
		}
	}
	executorService.shutdown();// 关闭线程池
	Collections.sort(result, new Comparator<AwbInfo>() {
		@Override
		public int compare(AwbInfo o1, AwbInfo o2) {
			return o1.getRowNumber().compareTo(o2.getRowNumber());
		}
	});
	return result;
}

4.最后这是dao层

	/**
    *
    * @函数名称:getAwbInfosV2
    * @创建日期:2019年9月17日10:55:46
    * @功能说明:销售系统---->运单查询---->excel导出部分数据
    * @参数说明:
    * @返回说明:List
    */
   public List<AwbInfo> getAwbInfosV2(int start, int end, List<String> fields, List<Where> wheres, List<Order> orders, UserAccount account)
           throws Exception {
       Map<String, Object> whereMap = this.generateWhere(wheres); // Generate
       //StringBuffer whereSb = (StringBuffer) whereMap.get(WHERE_IDS);
       Object[] objects = whereMap.get(WHERE_OBJECTS) == null ? null : (Object[]) whereMap.get(WHERE_OBJECTS);
       StringBuilder sqlSb = new StringBuilder();

       sqlSb.append(generateAwbQuerySql(start, end, wheres, orders, account));
       log.debug("SQL: " + sqlSb.toString());
       List<AwbInfo> resultList = this.getDataList(getJdbcTemplate(), sqlSb.toString(), objects);
       return resultList;
   }

5.excel表格的绘制(写的不是很优秀)

/**
 * @throws Exception 
 * @函数名称:export
* @创建日期:2018年9月10日
* @功能说明:导出数据
* @参数说明:
* @返回说明:void */
@Override public void export(Integer nti, List<AwbInfo> awbInfos, HttpServletRequest request, HttpServletResponse response, String operDateBeginQ, String operDateEndQ) throws Exception { try { // 产生工作簿对象 SXSSFWorkbook workbook = new SXSSFWorkbook(); // 产生工作表对象 Sheet sheet = workbook.createSheet("运单查询导出"); // 创建单元格样式,注意,这里只是声明,需要下面用到才可以 CellStyle style = workbook.createCellStyle(); style.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 垂直居中 style.setAlignment(HSSFCellStyle.ALIGN_CENTER);// 水平居中 CellStyle style_left = workbook.createCellStyle(); style_left.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER); style_left.setAlignment(HSSFCellStyle.ALIGN_LEFT); // 左对齐 CellStyle style2 = workbook.createCellStyle(); style2.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 垂直居中 style2.setAlignment(HSSFCellStyle.ALIGN_LEFT);// 水平居左 // 行是从0开始 String[] str = { "前缀", "单号", "运单状态", "制单时间", "制单人", "代理人", "始发站", "目的站", "航程", "航班日期", "开单航班", "走货航班", "发货人", "收货人", "承运人", "储运事项", "品名", "舱位", "件数", "重量", "计费重量", "费率", "航空运费", "总金额", "运价代码", "处理代码", "支付方式", "运单类型", "运输件数差额", "运输重量差额", "运输件数", "运输重量", "集装器", "运单来源" }; // s设置宽度 sheet.setColumnWidth(3, 5000); sheet.setColumnWidth(8, 4000); sheet.setColumnWidth(12, 5000); sheet.setColumnWidth(13, 5000); sheet.setColumnWidth(15, 4000); sheet.setColumnWidth(16, 5000); Row rowTop = sheet.createRow(0); // 列是从0开始, for (int i = 0; i < str.length; i++) { Cell cellTop = rowTop.createCell(i); cellTop.setCellValue(str[i]); cellTop.setCellStyle(style_left); } Map<String, String> dictInfos = dictInfoRedisDao.findAll("CABIN_LEVEL", BoolStatus.Y.getId()); // 合计 Double piecesTotal = 0d; Double weightTotal = 0d; Double chargeWeightTotal = 0d; Double feeRateTotal = 0d; Double totalfeeRateTotal = 0d; Double totalAllFeeTotal = 0d; int i = 0; // 下面就是循环生成,主要的内容了 start if (CollectionUtils.isNotEmpty(awbInfos)) { for (i = 0; i < awbInfos.size(); i++) { Row row = sheet.createRow(i + 1); row.createCell(0).setCellValue(awbInfos.get(i).getAwbPrefix()); row.createCell(1).setCellValue(awbInfos.get(i).getAwbNo()==null?null:Integer.parseInt(awbInfos.get(i).getAwbNo())); row.createCell(2).setCellValue(awbInfos.get(i).getStatus()); row.createCell(3).setCellValue(DateUtil.formatDate(awbInfos.get(i).getOperDate(), DateUtil.LONGDATE_DATETIME)); row.createCell(4).setCellValue(awbInfos.get(i).getOperName()); row.createCell(5).setCellValue(awbInfos.get(i).getAgentCode()); row.createCell(6).setCellValue(awbInfos.get(i).getDepCode()); row.createCell(7).setCellValue(awbInfos.get(i).getDestCode()); row.createCell(8).setCellValue(awbInfos.get(i).getFlightRoute() == null ? "" : awbInfos.get(i).getFlightRoute()); row.createCell(9).setCellValue(awbInfos.get(i).getFlightDate()); row.createCell(10).setCellValue(awbInfos.get(i).getFlightNo2()); row.createCell(11).setCellValue(awbInfos.get(i).getFlightNo() == null ? "" : awbInfos.get(i).getFlightNo()); row.createCell(12).setCellValue(sqlDecoding(awbInfos.get(i).getShpInfo())); row.createCell(13).setCellValue(sqlDecoding(awbInfos.get(i).getCneInfo())); row.createCell(14).setCellValue(sqlDecoding(awbInfos.get(i).getCarrierCode())); row.createCell(15).setCellValue(sqlDecoding(awbInfos.get(i).getTransNote())); row.createCell(16).setCellValue(sqlDecoding(awbInfos.get(i).getGoodsName())); row.createCell(17).setCellValue(dictInfos.get(awbInfos.get(i).getCabinLevel())); row.createCell(18).setCellValue(awbInfos.get(i).getPieces() == null ? 0.0 : awbInfos.get(i).getPieces()); row.createCell(19).setCellValue(awbInfos.get(i).getWeight() == null ? 0.0 : awbInfos.get(i).getWeight()); row.createCell(20).setCellValue(awbInfos.get(i).getChargeWeight() == null ? 0.0 : awbInfos.get(i).getChargeWeight()); row.createCell(21).setCellValue(awbInfos.get(i).getFeeRate() == null ? 0.0 : awbInfos.get(i).getFeeRate()); row.createCell(22).setCellValue(awbInfos.get(i).getTotalFee() == null ? 0.0 : awbInfos.get(i).getTotalFee()); row.createCell(23).setCellValue(awbInfos.get(i).getTotalAllFee() == null ? 0.0 : awbInfos.get(i).getTotalAllFee()); String aliasCode = StringUtils.isEmpty(awbInfos.get(i).getAliasCode()) ? "" : "(" + awbInfos.get(i).getAliasCode() + ")"; row.createCell(24).setCellValue(awbInfos.get(i).getBillCode() + aliasCode); row.createCell(25).setCellValue(awbInfos.get(i).getDealCode()); row.createCell(26).setCellValue(awbInfos.get(i).getPayType()); row.createCell(27).setCellValue(awbInfos.get(i).getEawb()); row.createCell(28).setCellValue(awbInfos.get(i).getPiecesDif() == null ? 0.0 : awbInfos.get(i).getPiecesDif()); row.createCell(29).setCellValue(awbInfos.get(i).getWeightDif() == null ? 0.0 : awbInfos.get(i).getWeightDif()); row.createCell(30).setCellValue(awbInfos.get(i).getTransPc() == null ? 0 : awbInfos.get(i).getTransPc()); row.createCell(31).setCellValue(awbInfos.get(i).getTransWeight() == null ? 0.0 : awbInfos.get(i).getTransWeight()); row.createCell(32).setCellValue(awbInfos.get(i).getActLocation() == null ? "" : awbInfos.get(i).getActLocation()); row.createCell(33).setCellValue(awbInfos.get(i).getSourceName()); // 合计 if (awbInfos.get(i).getPieces() != null) { piecesTotal += awbInfos.get(i).getPieces(); } if (awbInfos.get(i).getWeight() != null) { weightTotal += awbInfos.get(i).getWeight(); } if (awbInfos.get(i).getChargeWeight() != null) { chargeWeightTotal += awbInfos.get(i).getChargeWeight(); } if (awbInfos.get(i).getTotalFee() != null) { feeRateTotal += awbInfos.get(i).getTotalFee(); } if (awbInfos.get(i).getTotalAllFee() != null) { totalfeeRateTotal += awbInfos.get(i).getTotalAllFee(); } if (awbInfos.get(i).getTotalAllFee() != null) { totalAllFeeTotal += awbInfos.get(i).getTotalAllFee(); } for (int j = 0; j < str.length; j++) { if (j == 3 || j == 12 || j == 13 || j == 15 || j == 16) { row.getCell(j).setCellStyle(style2); } else { row.getCell(j).setCellStyle(style); } } } // 合计 Row row = sheet.createRow(i + 1); row.createCell(0).setCellValue("合计"); row.getCell(0).setCellStyle(style); row.createCell(1).setCellValue(""); row.getCell(1).setCellStyle(style); row.createCell(2).setCellValue(""); row.getCell(2).setCellStyle(style); row.createCell(3).setCellValue(""); row.getCell(3).setCellStyle(style); row.createCell(4).setCellValue(""); row.getCell(4).setCellStyle(style); row.createCell(5).setCellValue(""); row.getCell(5).setCellStyle(style); row.createCell(6).setCellValue(""); row.getCell(6).setCellStyle(style); row.createCell(7).setCellValue(""); row.getCell(7).setCellStyle(style); row.createCell(8).setCellValue(""); row.getCell(8).setCellStyle(style); row.createCell(9).setCellValue(""); row.getCell(9).setCellStyle(style); row.createCell(10).setCellValue(""); row.getCell(10).setCellStyle(style); row.createCell(11).setCellValue(""); row.getCell(11).setCellStyle(style); row.createCell(12).setCellValue(""); row.getCell(12).setCellStyle(style); row.createCell(13).setCellValue(""); row.getCell(13).setCellStyle(style); row.createCell(14).setCellValue(""); row.getCell(14).setCellStyle(style); row.createCell(15).setCellValue(""); row.getCell(15).setCellStyle(style); row.createCell(16).setCellValue(""); row.getCell(16).setCellStyle(style); row.createCell(17).setCellValue(""); row.getCell(17).setCellStyle(style); row.createCell(18).setCellValue(piecesTotal); row.getCell(18).setCellStyle(style); row.createCell(19).setCellValue(weightTotal); row.getCell(19).setCellStyle(style); row.createCell(20).setCellValue(chargeWeightTotal); row.getCell(20).setCellStyle(style); row.createCell(21).setCellValue(""); row.getCell(21).setCellStyle(style); row.createCell(22).setCellValue(feeRateTotal); row.getCell(22).setCellStyle(style); row.createCell(23).setCellValue(totalfeeRateTotal); row.getCell(23).setCellStyle(style); row.createCell(24).setCellValue(""); row.getCell(24).setCellStyle(style); row.createCell(25).setCellValue(""); row.getCell(25).setCellStyle(style); row.createCell(26).setCellValue(""); row.getCell(26).setCellStyle(style); row.createCell(27).setCellValue(""); row.getCell(27).setCellStyle(style); row.createCell(28).setCellValue(""); row.getCell(28).setCellStyle(style); row.createCell(29).setCellValue(""); row.getCell(29).setCellStyle(style); row.createCell(30).setCellValue(""); row.getCell(30).setCellStyle(style); row.createCell(31).setCellValue(""); row.getCell(31).setCellStyle(style); row.createCell(32).setCellValue(""); row.getCell(32).setCellStyle(style); row.createCell(33).setCellValue(""); row.getCell(33).setCellStyle(style); } // 下面是封装好的方法,第一个参数,是文件名,第二个是上面的工作薄对象, new ExcelUtil().doExcel("AwbQueryExport", workbook, request, response); } catch (Exception e) { e.printStackTrace(); throw new Exception("操作异常"); } }

6.excel工具类

/**
	 * 
	 * @函数名称:doExcel
	 * @创建日期:2019年9月23日
	 * @author HjwJames
	 * @功能说明:导出新版excel 可容纳多数据格式 xlsx,处理大量导出(超过6.5W条数据)
	 * @参数说明:
	 * @返回说明:void
	 */
	public void doExcel(String fileName, XSSFWorkbook workbookList, HttpServletRequest request, HttpServletResponse response) {
		// TODO Auto-generated method stub
		HttpSession session = request.getSession();
		session.setAttribute("state", null);
		// 生成提示信息
		OutputStream fOut = null;
		try {
			response.setCharacterEncoding("utf-8");
			response.setHeader("content-disposition", "attachment;filename=" + new String(fileName.getBytes("utf-8"), "ISO8859-1") + ".xlsx");
			// 产生工作簿对象
			XSSFWorkbook workbook = workbookList;
			fOut = response.getOutputStream();
			workbook.write(fOut);
		} catch (UnsupportedEncodingException e1) {

		} catch (Exception e) {

		} finally {
			try {
				fOut.flush();
				fOut.close();
			} catch (IOException e) {

			}
			session.setAttribute("state", "open");
		}
	}

2.多线程导入

1.首先Controller层与html对接,很普通没什么好讲解的

/**
 * 
 * @函数名称:importExcel
* @创建日期:2019年4月30日
* @功能说明:
excel导入 * @参数说明:
* @返回说明:ModelAndView
*/
@RequestMapping(value = "/uploadify") public ModelAndView importExcel(@RequestParam("file") MultipartFile file, HttpServletRequest request, boolean isCustFlag, boolean importflag) throws Exception { String errorMessage = null;// 错误信息 if (file != null) {// 判断上传的文件是否为空 String type = null;// 文件类型 String fileName = file.getOriginalFilename();// 文件原名称 type = fileName.indexOf(".") != -1 ? fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length()) : null;// 文件类型 if (type != null) {// 判断文件类型是否为空 if ("XLS".equals(type.toUpperCase()) || "XLSX".equals(type.toUpperCase())) { errorMessage = dangerSpecialService.readFile(file, isCustFlag, importflag);// 读取excel文件 TODO } else { errorMessage = "请选择正确的excel文件!"; } } else { errorMessage = "文件类型为空!"; } } else { errorMessage = "请选择上传文件!"; } if (StringUtils.isNotEmpty(errorMessage)) { return ajaxDoneError(errorMessage); } else { return ajaxDoneSuccess("文件上传成功!"); } }

2.service层,验证参数是否为空,是否合法。最后指引到多线程上传路层
详解:1.首先多线程导入需要用多Collections.synchronizedList ,多线程list
2.遍历excel和object的映射机制将数据并上传到List中
3.当数据处理好转换成list时交给下一步多线程上传

/**
	 * 用于excel导入
	 * 从file中读取数据到list
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public String readFile(MultipartFile file, boolean isCustFlag, boolean type) throws Exception {
		try {
			String[] fields = new String[] { "dsName", "goodName", "dealCode" };
			Workbook wb = WorkbookFactory.create(file.getInputStream());
			Sheet sheet = wb.getSheetAt(0);// 读取第一个sheet
			Row row = null;
			int index = 0;// 行号
			int lastRowNum = fields.length;// 总列数
			Iterator<Row> rowIterator = sheet.iterator();
			List<DangerSpecialXls> list = Collections.synchronizedList(new ArrayList<>());
			while (rowIterator.hasNext()) {
				index++;
				row = rowIterator.next();
				DangerSpecialXls hdgXls = new DangerSpecialXls();
				if (index == 1) {
					// 当index=1时,第一行为标题
					continue;
				}
				if (null == row) {
					// 当row为空时,为空行,跳过
					continue;
				}
				hdgXls.setRowId(index);// 设置行号
				for (int i = 0; i < lastRowNum; i++) {
					Integer columnIndex = 0;// 单元格号
					try {
						Cell cell = row.getCell(i);
						if (i == 0 && null == cell) {
							throw new Exception("导入错误,xls第" + hdgXls.getRowId() + "行第" + (i + 1) + "列为空单元格!");
						}
						String res = "";
						if (cell != null) {// 当cell为空时,给默认string “”
							columnIndex = cell.getColumnIndex();
							// 将数字或其他类型强制转化位string
							cell.setCellType(XSSFCell.CELL_TYPE_STRING);
							res = this.getCellValue(cell);
							// 双重验证
							if (columnIndex == 0 && StringUtils.isBlank(this.getCellValue(cell))) {
								// 校验必填项
								throw new Exception("导入错误,xls第" + hdgXls.getRowId() + "行第" + (columnIndex + 1) + "列为空单元格!");
							}
						} else {
							columnIndex = i;
							res = "";
						}
						objSetValue(hdgXls, fields[columnIndex], res);
					} catch (Exception e) {
						log.error("导入错误,xls第" + hdgXls.getRowId() + "行第" + (columnIndex + 1) + "列错误!", e);
						if (StringUtils.isEmpty(e.getMessage())) {
							throw new Exception("导入错误,xls第" + hdgXls.getRowId() + "行第" + (columnIndex + 1) + "列错误!");
						} else {
							throw new Exception(e.getMessage());
						}
					}
				}
				list.add(hdgXls);
			}
			String res = checkDataAndSave(list, isCustFlag, type);
			return res;
		} catch (Exception e) {
			e.printStackTrace();
			return e.getMessage();
		}
	}

3.映射基类

/**
 * @函数名称:objSetValue
 * @创建日期:
 * @功能说明:通过反射给Object设值
 * @参数说明:
 * @返回说明:void
 */
private void objSetValue(Object obj, String fieldName, String fieldValue) {
	try {
		Class class1 = obj.getClass();
		Field[] fields = class1.getDeclaredFields();
		for (Field field : fields) {
			field.setAccessible(true);
			String name = field.getName().toLowerCase();
			if (name.equals(fieldName.toLowerCase())) {
				field.set(obj, fieldValue);
				break;
			}
		}
	} catch (Exception e) {
		e.printStackTrace();
	}
}

4.多线程上传
详情解析:1.开启forkjoin线程池ForkJoinPool(32)
2.用java8 新特性stream写法遍历list myPool.submit(() -> list.parallelStream().forEach
获取单个xls类
3.xls进行数据校验
4.导入单条数据,并做好exception捕获

/**
 * 
 * @函数名称:checkDataAndSave
 * @创建日期:2019年4月17日
 * @功能说明:只用于导入 数据验证与输入
 * @参数说明:
 * @返回说明:void
 */
private String checkDataAndSave(List<DangerSpecialXls> list, boolean isCustFlag, boolean type) throws Exception {
	if (CollectionUtils.isEmpty(list)) {
		throw new Exception("导入数据不能为空!");
	}
	List<Integer> errorList = new ArrayList<Integer>();
	List<String> resList = new ArrayList<String>();
	ForkJoinPool myPool = new ForkJoinPool(32);
	Date date = new Date();
	Integer ver = dangerSpecialDao.getVerIdSequence();// 获取ver批次号
	myPool.submit(() -> list.parallelStream().forEach(xls -> {
		try {
			DangerSpecial hg = new DangerSpecial();
			// hg.setDangerId(Integer.parseInt(xls.getDangerId())); id 自增不需要填写
			if (xls.getGoodName().contains("!") || xls.getGoodName().contains("@") || xls.getGoodName().contains("#")
					|| xls.getGoodName().contains("*") || xls.getGoodName().contains("/") || xls.getGoodName().contains("$")
					|| xls.getGoodName().contains("%") || xls.getGoodName().contains("&") || xls.getGoodName().contains("'")
					|| xls.getGoodName().contains("\"") || xls.getGoodName().contains(";")) {

				resList.add("第" + xls.getRowId() + "行:存在特殊字符;");
			} else if (xls.getDsName().contains("!") || xls.getDsName().contains("@") || xls.getDsName().contains("#")
					|| xls.getDsName().contains("*") || xls.getDsName().contains("/") || xls.getDsName().contains("$")
					|| xls.getDsName().contains("%") || xls.getDsName().contains("&") || xls.getDsName().contains("'")
					|| xls.getDsName().contains("\"") || xls.getDsName().contains(";") || xls.getDsName().contains(",")) {

				resList.add("第" + xls.getRowId() + "行:存在特殊字符;");
			} else {

				// 导入单条数据
				String[] mes = iDangerSpecialService.importSingleDate(xls, type, isCustFlag, date, ver);
				String res = "";

				if (null != mes) {
					if (StringUtils.isNotEmpty(mes[0])) {
						res += "第" + xls.getRowId() + "行:配置品名[" + mes[0] + "]异常;";
					}
					if (StringUtils.isNotEmpty(mes[1])) {
						if (StringUtils.isEmpty(mes[0])) {
							res += "第" + xls.getRowId() + "行:";
						}
						mes[1] = mes[1].substring(0, mes[1].length() - 1);
						res += "处理代码[" + mes[1] + "]不存在或异常";
					}
				}

				if (StringUtils.isNotEmpty(res)) {
					resList.add(res);
				}

			}
		} catch (Exception e) {

			String error = e.getMessage();
			String res = "";
			if (error.equals("参数异常")) {
				res += "第" + xls.getRowId() + "行:" + e.getMessage();
			} else {
				res += "第" + xls.getRowId() + "行:" + "参数异常!";
			}
			if (StringUtils.isNotEmpty(res)) {
				resList.add(res);
			}

		}
	})).get();

	if (CollectionUtils.isNotEmpty(resList)) {
		Collections.sort(resList);
		StringBuffer msg = new StringBuffer("导入错误。");
		for (int i = 0; i < resList.size(); i++) {
			msg.append(resList.get(i));
		}
		// throw new Exception(msg.toString());
		return msg.toString();
	}

	return null;

}

5.Dao层importSingleDate数据添加(无关痛痒的Dao数据存储)

/**
	 * 
	 * @throws Exception 
	 * @函数名称:importSingleDate
	 * @创建日期:2019年5月15日
	 * @功能说明:用于批量导入中单条数据导入处理
	 * @参数说明:importflag true -->追加 / false -->替换  / ver--->version批次号
	 * @返回说明:DangerSpecial
	 */
	@Override
//	@Transactional(rollbackFor = Exception.class)
	public String[] importSingleDate(DangerSpecialXls xls, Boolean importflag, boolean isCustFlag, Date date, Integer verion) throws Exception {
		String mes1 = "";// SpecialGood 错误报告
		String mes2 = "";// DangerDeal 错误报告
		DangerSpecial hg = new DangerSpecial();
		String ver = Integer.toString(verion);// 版本批次号
		// 获取固定条件
		List<Where> wheres = new ArrayList<Where>();
		wheres.add(new Where("DS_NAME", xls.getDsName().toUpperCase()));
		try {
			UserAccount userAccount = (UserAccount) SecurityUtils.getSubject().getPrincipal();
			if (importflag == true) {
				// 追加导入
				DangerSpecial ds = dangerSpecialDao.find(wheres);
				if (null == ds) {// 主表不存在,导入主表,再导入从表

					// 主表新增
					Integer dsId = this.insertXls(xls, userAccount, isCustFlag, date, ver);
					// 新增到危险品及特种货物分类绑定品名表
					mes1 = this.insertMultiSpecialGood(xls, userAccount, date, ver, dsId);/// TODO
					// 新增到危险品及特种货物分类绑定处理代码
					mes2 = this.insertMultiDangerDeal(xls, userAccount, date, ver, dsId);// TODO
				} else {// 主表存在,更新主表,追加导入从表

					// 更新主表,追加导入
					String mes3 = this.updateAddXls(xls, userAccount, isCustFlag, date, ver, ds, wheres);

					// 新增到危险品及特种货物分类绑定品名表
					Integer dsId = ds.getDsId();
					mes1 = this.insertAddMultiSpecialGood(xls, userAccount, date, ver, dsId);
					// 新增到危险品及特种货物分类绑定处理代码
					mes2 = this.insertAddMultiDangerDeal(xls, userAccount, date, ver, dsId);
					/*
					 * if(StringUtils.isNotEmpty(mes3)) { mes2 += mes3; }
					 */
				}
			} else {
				// 替换导入

				DangerSpecial ds = dangerSpecialDao.find(wheres);
				if (null == ds) {// 主表不存在数据,导入主表,再导入从表

					// 主表新增
					Integer dsId = this.insertXls(xls, userAccount, isCustFlag, date, ver);
					// 先删除从表,新增到危险品及特种货物分类绑定品名表
					List<Where> tmpwhere = new ArrayList<Where>();
					tmpwhere.add(new Where("DS_ID", dsId));
					specialGoodDao.delete(tmpwhere);
					// 从表新增,批量新增multiInsert
					mes1 = this.insertMultiSpecialGood(xls, userAccount, date, ver, dsId);
					// 先删除从表,新增到危险品及特种货物分类绑定处理代码
					tmpwhere = new ArrayList<Where>();
					tmpwhere.add(new Where("DS_ID", dsId));
					dangerSpecialDealDao.delete(tmpwhere);
					// 从表新增
					mes2 = this.insertMultiDangerDeal(xls, userAccount, date, ver, dsId);

				} else {// 主表存在相同数据,主表更新数据,先删除从表数据,再导入从表

					// 更新主表,覆盖导入
					this.updateXls(xls, userAccount, isCustFlag, date, ver, ds, wheres);
					// 删除从表
					Integer dsId = ds.getDsId();
					List<Where> tmpwhere = new ArrayList<Where>();
					tmpwhere.add(new Where("DS_ID", dsId));
					dangerSpecialDealDao.delete(tmpwhere);
					specialGoodDao.delete(tmpwhere);
					// 新增到危险品及特种货物分类绑定品名表
					mes1 = this.insertMultiSpecialGood(xls, userAccount, date, ver, dsId);
					// 新增到危险品及特种货物分类绑定处理代码
					mes2 = this.insertMultiDangerDeal(xls, userAccount, date, ver, dsId);

				}
			}

			if (StringUtils.isNotEmpty(mes1) || StringUtils.isNotEmpty(mes2)) {
				String res = new String();
				res = mes1 + "///" + mes2;
				// throw new Exception(res);//TODO
				String[] s = new String[2];
				s[0] = mes1;
				s[1] = mes2;
				return s;
			}

			return null;
		} catch (Exception e) {
			e.printStackTrace();
			throw new Exception(e.getMessage());// TODO
		}
	}

你可能感兴趣的:(java)