|
|
@ -32,7 +32,11 @@ import java.net.URLEncoder; |
|
|
import java.text.ParseException; |
|
|
import java.text.ParseException; |
|
|
import java.text.SimpleDateFormat; |
|
|
import java.text.SimpleDateFormat; |
|
|
import java.time.LocalDate; |
|
|
import java.time.LocalDate; |
|
|
|
|
|
import java.time.LocalDateTime; |
|
|
|
|
|
import java.time.ZoneId; |
|
|
import java.time.format.DateTimeFormatter; |
|
|
import java.time.format.DateTimeFormatter; |
|
|
|
|
|
import java.time.format.DateTimeFormatterBuilder; |
|
|
|
|
|
import java.time.format.DateTimeParseException; |
|
|
import java.util.*; |
|
|
import java.util.*; |
|
|
import java.util.concurrent.atomic.AtomicLong; |
|
|
import java.util.concurrent.atomic.AtomicLong; |
|
|
import java.util.zip.ZipEntry; |
|
|
import java.util.zip.ZipEntry; |
|
|
@ -198,41 +202,37 @@ public class MesTidEpcLogServiceImpl extends ServiceImpl<MesTidEpcLogMapper, Mes |
|
|
// 列0: 序号 |
|
|
// 列0: 序号 |
|
|
entity.setSeqNo(getCellValue(row.getCell(0), dataFormatter)); |
|
|
entity.setSeqNo(getCellValue(row.getCell(0), dataFormatter)); |
|
|
// 列1: EPC |
|
|
// 列1: EPC |
|
|
entity.setEpc(getCellValue(row.getCell(1), dataFormatter)); |
|
|
|
|
|
|
|
|
entity.setEpc(getCellValue(row.getCell(2), dataFormatter)); |
|
|
// 列2: TID |
|
|
// 列2: TID |
|
|
entity.setTid(getCellValue(row.getCell(2), dataFormatter)); |
|
|
|
|
|
|
|
|
entity.setTid(getCellValue(row.getCell(3), dataFormatter)); |
|
|
// 列3: 用户区 |
|
|
// 列3: 用户区 |
|
|
entity.setUserArea(getCellValue(row.getCell(3), dataFormatter)); |
|
|
|
|
|
|
|
|
entity.setUserArea(getCellValue(row.getCell(4), dataFormatter)); |
|
|
// 列4: LockiBtis |
|
|
// 列4: LockiBtis |
|
|
entity.setLockBits(getCellValue(row.getCell(4), dataFormatter)); |
|
|
|
|
|
|
|
|
entity.setLockBits(getCellValue(row.getCell(5), dataFormatter)); |
|
|
// 列5: 密匙 |
|
|
// 列5: 密匙 |
|
|
entity.setSecretKey(getCellValue(row.getCell(5), dataFormatter)); |
|
|
|
|
|
|
|
|
entity.setSecretKey(getCellValue(row.getCell(6), dataFormatter)); |
|
|
// 列6: 写码成功 |
|
|
// 列6: 写码成功 |
|
|
entity.setWriteSuccess(getCellValue(row.getCell(6), dataFormatter)); |
|
|
|
|
|
|
|
|
entity.setWriteSuccess(getCellValue(row.getCell(7), dataFormatter)); |
|
|
// 列7: 读码成功 |
|
|
// 列7: 读码成功 |
|
|
entity.setReadSuccess(getCellValue(row.getCell(7), dataFormatter)); |
|
|
|
|
|
|
|
|
entity.setReadSuccess(getCellValue(row.getCell(8), dataFormatter)); |
|
|
// 列8: EPC锁定 |
|
|
// 列8: EPC锁定 |
|
|
entity.setEpcLocked(getCellValue(row.getCell(8), dataFormatter)); |
|
|
|
|
|
|
|
|
entity.setEpcLocked(getCellValue(row.getCell(9), dataFormatter)); |
|
|
// 列9: 强度/读距 |
|
|
// 列9: 强度/读距 |
|
|
entity.setSignalStrength(getCellValue(row.getCell(9), dataFormatter)); |
|
|
|
|
|
|
|
|
entity.setSignalStrength(getCellValue(row.getCell(10), dataFormatter)); |
|
|
// 列10: 时间 |
|
|
// 列10: 时间 |
|
|
Cell timeCell = row.getCell(10); |
|
|
|
|
|
|
|
|
Cell timeCell = row.getCell(11); |
|
|
if (timeCell != null) { |
|
|
if (timeCell != null) { |
|
|
if (timeCell.getCellType() == CellType.NUMERIC && DateUtil.isCellDateFormatted(timeCell)) { |
|
|
if (timeCell.getCellType() == CellType.NUMERIC && DateUtil.isCellDateFormatted(timeCell)) { |
|
|
entity.setScanTime(timeCell.getDateCellValue()); |
|
|
entity.setScanTime(timeCell.getDateCellValue()); |
|
|
} else { |
|
|
} else { |
|
|
String timeStr = getCellValue(timeCell, dataFormatter); |
|
|
String timeStr = getCellValue(timeCell, dataFormatter); |
|
|
if (StringUtils.hasText(timeStr)) { |
|
|
if (StringUtils.hasText(timeStr)) { |
|
|
try { |
|
|
|
|
|
entity.setScanTime(sdf.parse(timeStr)); |
|
|
|
|
|
} catch (ParseException e) { |
|
|
|
|
|
log.warn("第{}行时间格式解析失败: {} - rqrq", rowNum + 1, timeStr); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
entity.setScanTime(parseDate(timeStr)); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
// 列11: 计数 |
|
|
// 列11: 计数 |
|
|
entity.setCountInfo(getCellValue(row.getCell(11), dataFormatter)); |
|
|
|
|
|
|
|
|
entity.setCountInfo(getCellValue(row.getCell(12), dataFormatter)); |
|
|
|
|
|
|
|
|
dataList.add(entity); |
|
|
dataList.add(entity); |
|
|
} |
|
|
} |
|
|
@ -241,6 +241,26 @@ public class MesTidEpcLogServiceImpl extends ServiceImpl<MesTidEpcLogMapper, Mes |
|
|
return dataList; |
|
|
return dataList; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static Date parseDate(String timeStr) { |
|
|
|
|
|
DateTimeFormatter FORMATTER = |
|
|
|
|
|
new DateTimeFormatterBuilder() |
|
|
|
|
|
.appendOptional(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) |
|
|
|
|
|
.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) |
|
|
|
|
|
.toFormatter(); |
|
|
|
|
|
try { |
|
|
|
|
|
|
|
|
|
|
|
LocalDateTime localDateTime = |
|
|
|
|
|
LocalDateTime.parse(timeStr, FORMATTER); |
|
|
|
|
|
|
|
|
|
|
|
return Date.from( |
|
|
|
|
|
localDateTime.atZone(ZoneId.systemDefault()).toInstant() |
|
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
} catch (DateTimeParseException e) { |
|
|
|
|
|
|
|
|
|
|
|
throw new RuntimeException("时间格式错误: " + timeStr, e); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
/** |
|
|
/** |
|
|
* @Description 获取单元格值 - rqrq |
|
|
* @Description 获取单元格值 - rqrq |
|
|
* @param cell 单元格 |
|
|
* @param cell 单元格 |
|
|
@ -297,7 +317,7 @@ public class MesTidEpcLogServiceImpl extends ServiceImpl<MesTidEpcLogMapper, Mes |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* @Description 导出CSV文件(真正的流式导出:MyBatis ResultHandler + 逐行写入)- rqrq |
|
|
* @Description 导出CSV文件(真正的流式导出:MyBatis ResultHandler + 逐行写入)- rqrq |
|
|
* |
|
|
|
|
|
|
|
|
* |
|
|
* <p><b>【V5版本:真正的流式导出】</b></p> |
|
|
* <p><b>【V5版本:真正的流式导出】</b></p> |
|
|
* <ul> |
|
|
* <ul> |
|
|
* <li>使用 MyBatis ResultHandler 逐行从数据库读取</li> |
|
|
* <li>使用 MyBatis ResultHandler 逐行从数据库读取</li> |
|
|
@ -305,14 +325,14 @@ public class MesTidEpcLogServiceImpl extends ServiceImpl<MesTidEpcLogMapper, Mes |
|
|
* <li>配合 JDBC responseBuffering=adaptive 和 FORWARD_ONLY 游标</li> |
|
|
* <li>配合 JDBC responseBuffering=adaptive 和 FORWARD_ONLY 游标</li> |
|
|
* <li>真正的 O(1) 内存占用,可导出任意大小数据集</li> |
|
|
* <li>真正的 O(1) 内存占用,可导出任意大小数据集</li> |
|
|
* </ul> |
|
|
* </ul> |
|
|
* |
|
|
|
|
|
|
|
|
* |
|
|
* <p><b>【导出策略】</b></p> |
|
|
* <p><b>【导出策略】</b></p> |
|
|
* <ul> |
|
|
* <ul> |
|
|
* <li>数据量 ≤ 100万:返回单个CSV文件</li> |
|
|
* <li>数据量 ≤ 100万:返回单个CSV文件</li> |
|
|
* <li>数据量 > 100万:返回ZIP压缩包,每个CSV最多100万条</li> |
|
|
* <li>数据量 > 100万:返回ZIP压缩包,每个CSV最多100万条</li> |
|
|
* <li>数据量 > 500万:提示用户缩小范围分批导出</li> |
|
|
* <li>数据量 > 500万:提示用户缩小范围分批导出</li> |
|
|
* </ul> |
|
|
* </ul> |
|
|
* |
|
|
|
|
|
|
|
|
* |
|
|
* @param data 查询条件 |
|
|
* @param data 查询条件 |
|
|
* @param response HttpServletResponse |
|
|
* @param response HttpServletResponse |
|
|
* @author rqrq |
|
|
* @author rqrq |
|
|
@ -364,14 +384,14 @@ public class MesTidEpcLogServiceImpl extends ServiceImpl<MesTidEpcLogMapper, Mes |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* @Description 真正的流式CSV导出(单文件)- rqrq |
|
|
* @Description 真正的流式CSV导出(单文件)- rqrq |
|
|
* |
|
|
|
|
|
|
|
|
* |
|
|
* <p><b>【核心原理】</b></p> |
|
|
* <p><b>【核心原理】</b></p> |
|
|
* <ul> |
|
|
* <ul> |
|
|
* <li>MyBatis ResultHandler 逐行回调</li> |
|
|
* <li>MyBatis ResultHandler 逐行回调</li> |
|
|
* <li>每收到一行数据立即写入CSV</li> |
|
|
* <li>每收到一行数据立即写入CSV</li> |
|
|
* <li>内存中始终只有1行数据</li> |
|
|
* <li>内存中始终只有1行数据</li> |
|
|
* </ul> |
|
|
* </ul> |
|
|
* |
|
|
|
|
|
|
|
|
* |
|
|
* @param data 查询条件 |
|
|
* @param data 查询条件 |
|
|
* @param dataTotal 数据总数 |
|
|
* @param dataTotal 数据总数 |
|
|
* @param response HttpServletResponse |
|
|
* @param response HttpServletResponse |
|
|
@ -448,7 +468,7 @@ public class MesTidEpcLogServiceImpl extends ServiceImpl<MesTidEpcLogMapper, Mes |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* @Description 真正的流式ZIP导出(多CSV文件)- rqrq |
|
|
* @Description 真正的流式ZIP导出(多CSV文件)- rqrq |
|
|
* |
|
|
|
|
|
|
|
|
* |
|
|
* <p><b>【核心原理】</b></p> |
|
|
* <p><b>【核心原理】</b></p> |
|
|
* <ul> |
|
|
* <ul> |
|
|
* <li>MyBatis ResultHandler 逐行回调</li> |
|
|
* <li>MyBatis ResultHandler 逐行回调</li> |
|
|
@ -456,7 +476,7 @@ public class MesTidEpcLogServiceImpl extends ServiceImpl<MesTidEpcLogMapper, Mes |
|
|
* <li>当前CSV达到100万行自动切换到新CSV</li> |
|
|
* <li>当前CSV达到100万行自动切换到新CSV</li> |
|
|
* <li>内存中始终只有1行数据</li> |
|
|
* <li>内存中始终只有1行数据</li> |
|
|
* </ul> |
|
|
* </ul> |
|
|
* |
|
|
|
|
|
|
|
|
* |
|
|
* @param data 查询条件 |
|
|
* @param data 查询条件 |
|
|
* @param dataTotal 数据总数 |
|
|
* @param dataTotal 数据总数 |
|
|
* @param response HttpServletResponse |
|
|
* @param response HttpServletResponse |
|
|
@ -536,10 +556,10 @@ public class MesTidEpcLogServiceImpl extends ServiceImpl<MesTidEpcLogMapper, Mes |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* @Description 【V4备份】写入ZIP压缩包(伪流式:分批查询分批写入)- rqrq |
|
|
* @Description 【V4备份】写入ZIP压缩包(伪流式:分批查询分批写入)- rqrq |
|
|
* |
|
|
|
|
|
|
|
|
* |
|
|
* <p><b>【已被V5取代】</b>保留此方法用于对比或回退</p> |
|
|
* <p><b>【已被V5取代】</b>保留此方法用于对比或回退</p> |
|
|
* <p><b>【调用方式】</b>如需使用,在exportCsv方法中替换exportToZipRealStreaming为此方法</p> |
|
|
* <p><b>【调用方式】</b>如需使用,在exportCsv方法中替换exportToZipRealStreaming为此方法</p> |
|
|
* |
|
|
|
|
|
|
|
|
* |
|
|
* @param data 查询条件 |
|
|
* @param data 查询条件 |
|
|
* @param dataTotal 数据总数 |
|
|
* @param dataTotal 数据总数 |
|
|
* @param response HttpServletResponse |
|
|
* @param response HttpServletResponse |
|
|
@ -549,7 +569,7 @@ public class MesTidEpcLogServiceImpl extends ServiceImpl<MesTidEpcLogMapper, Mes |
|
|
@SuppressWarnings("unused") |
|
|
@SuppressWarnings("unused") |
|
|
private void writeToZipWithMultipleCsv(MesTidEpcLogData data, long dataTotal, HttpServletResponse response) throws IOException { |
|
|
private void writeToZipWithMultipleCsv(MesTidEpcLogData data, long dataTotal, HttpServletResponse response) throws IOException { |
|
|
log.info("开始生成ZIP压缩包(多CSV),数据总数: {} 条 - rqrq", dataTotal); |
|
|
log.info("开始生成ZIP压缩包(多CSV),数据总数: {} 条 - rqrq", dataTotal); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 设置响应头(ZIP格式)- rqrq |
|
|
// 设置响应头(ZIP格式)- rqrq |
|
|
response.setContentType("application/zip"); |
|
|
response.setContentType("application/zip"); |
|
|
response.setCharacterEncoding("UTF-8"); |
|
|
response.setCharacterEncoding("UTF-8"); |
|
|
@ -563,7 +583,7 @@ public class MesTidEpcLogServiceImpl extends ServiceImpl<MesTidEpcLogMapper, Mes |
|
|
try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) { |
|
|
try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) { |
|
|
int pageSize = EXPORT_BATCH_SIZE; |
|
|
int pageSize = EXPORT_BATCH_SIZE; |
|
|
int totalPages = (int) Math.ceil((double) dataTotal / pageSize); |
|
|
int totalPages = (int) Math.ceil((double) dataTotal / pageSize); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
long totalWritten = 0; // 总共已写入的行数 |
|
|
long totalWritten = 0; // 总共已写入的行数 |
|
|
int currentCsvIndex = 1; // 当前CSV文件编号 |
|
|
int currentCsvIndex = 1; // 当前CSV文件编号 |
|
|
long currentCsvRows = 0; // 当前CSV已写入的行数 |
|
|
long currentCsvRows = 0; // 当前CSV已写入的行数 |
|
|
@ -593,13 +613,13 @@ public class MesTidEpcLogServiceImpl extends ServiceImpl<MesTidEpcLogMapper, Mes |
|
|
log.info("CSV文件 {} 写入完成,共 {} 条 - rqrq", currentCsvIndex, currentCsvRows); |
|
|
log.info("CSV文件 {} 写入完成,共 {} 条 - rqrq", currentCsvIndex, currentCsvRows); |
|
|
currentCsvIndex++; |
|
|
currentCsvIndex++; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 创建新的CSV文件 - rqrq |
|
|
// 创建新的CSV文件 - rqrq |
|
|
String csvFileName = "TID_EPC日志_" + currentCsvIndex + ".csv"; |
|
|
String csvFileName = "TID_EPC日志_" + currentCsvIndex + ".csv"; |
|
|
ZipEntry zipEntry = new ZipEntry(csvFileName); |
|
|
ZipEntry zipEntry = new ZipEntry(csvFileName); |
|
|
zipOut.putNextEntry(zipEntry); |
|
|
zipOut.putNextEntry(zipEntry); |
|
|
currentWriter = new BufferedWriter(new OutputStreamWriter(zipOut, "GB18030"), 8192 * 16); |
|
|
currentWriter = new BufferedWriter(new OutputStreamWriter(zipOut, "GB18030"), 8192 * 16); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 写入表头 - rqrq |
|
|
// 写入表头 - rqrq |
|
|
currentWriter.write(csvHeader); |
|
|
currentWriter.write(csvHeader); |
|
|
currentWriter.newLine(); |
|
|
currentWriter.newLine(); |
|
|
@ -623,7 +643,7 @@ public class MesTidEpcLogServiceImpl extends ServiceImpl<MesTidEpcLogMapper, Mes |
|
|
sb.append(escapeCsvAsText(row.getCountInfo())); |
|
|
sb.append(escapeCsvAsText(row.getCountInfo())); |
|
|
currentWriter.write(sb.toString()); |
|
|
currentWriter.write(sb.toString()); |
|
|
currentWriter.newLine(); |
|
|
currentWriter.newLine(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
currentCsvRows++; |
|
|
currentCsvRows++; |
|
|
totalWritten++; |
|
|
totalWritten++; |
|
|
} |
|
|
} |
|
|
@ -656,10 +676,10 @@ public class MesTidEpcLogServiceImpl extends ServiceImpl<MesTidEpcLogMapper, Mes |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* @Description 写入方式1:EasyExcel默认版 - rqrq |
|
|
* @Description 写入方式1:EasyExcel默认版 - rqrq |
|
|
* |
|
|
|
|
|
|
|
|
* |
|
|
* <p><b>特点:</b>使用EasyExcel默认配置,支持注解样式</p> |
|
|
* <p><b>特点:</b>使用EasyExcel默认配置,支持注解样式</p> |
|
|
* <p><b>预计耗时:</b>50万条约35-40秒</p> |
|
|
* <p><b>预计耗时:</b>50万条约35-40秒</p> |
|
|
* |
|
|
|
|
|
|
|
|
* |
|
|
* @param dataList 数据列表 |
|
|
* @param dataList 数据列表 |
|
|
* @param response HttpServletResponse |
|
|
* @param response HttpServletResponse |
|
|
* @author rqrq |
|
|
* @author rqrq |
|
|
@ -708,10 +728,10 @@ public class MesTidEpcLogServiceImpl extends ServiceImpl<MesTidEpcLogMapper, Mes |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* @Description 写入方式2:EasyExcel优化版(关闭自动列宽等)- rqrq |
|
|
* @Description 写入方式2:EasyExcel优化版(关闭自动列宽等)- rqrq |
|
|
* |
|
|
|
|
|
|
|
|
* |
|
|
* <p><b>特点:</b>关闭自动列宽计算,使用inMemory模式</p> |
|
|
* <p><b>特点:</b>关闭自动列宽计算,使用inMemory模式</p> |
|
|
* <p><b>预计耗时:</b>50万条约25-30秒</p> |
|
|
* <p><b>预计耗时:</b>50万条约25-30秒</p> |
|
|
* |
|
|
|
|
|
|
|
|
* |
|
|
* @param dataList 数据列表 |
|
|
* @param dataList 数据列表 |
|
|
* @param response HttpServletResponse |
|
|
* @param response HttpServletResponse |
|
|
* @author rqrq |
|
|
* @author rqrq |
|
|
@ -764,11 +784,11 @@ public class MesTidEpcLogServiceImpl extends ServiceImpl<MesTidEpcLogMapper, Mes |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* @Description 写入方式3:CSV纯文本版(最快)- rqrq |
|
|
* @Description 写入方式3:CSV纯文本版(最快)- rqrq |
|
|
* |
|
|
|
|
|
|
|
|
* |
|
|
* <p><b>特点:</b>直接写入CSV文本,无Excel格式处理开销</p> |
|
|
* <p><b>特点:</b>直接写入CSV文本,无Excel格式处理开销</p> |
|
|
* <p><b>预计耗时:</b>50万条约3-5秒</p> |
|
|
* <p><b>预计耗时:</b>50万条约3-5秒</p> |
|
|
* <p><b>注意:</b>CSV无多Sheet支持,大文件用Excel打开可能卡</p> |
|
|
* <p><b>注意:</b>CSV无多Sheet支持,大文件用Excel打开可能卡</p> |
|
|
* |
|
|
|
|
|
|
|
|
* |
|
|
* @param dataList 数据列表 |
|
|
* @param dataList 数据列表 |
|
|
* @param response HttpServletResponse |
|
|
* @param response HttpServletResponse |
|
|
* @author rqrq |
|
|
* @author rqrq |
|
|
@ -787,7 +807,7 @@ public class MesTidEpcLogServiceImpl extends ServiceImpl<MesTidEpcLogMapper, Mes |
|
|
|
|
|
|
|
|
// 使用BufferedWriter提高写入性能 - rqrq |
|
|
// 使用BufferedWriter提高写入性能 - rqrq |
|
|
java.io.BufferedWriter writer = new java.io.BufferedWriter( |
|
|
java.io.BufferedWriter writer = new java.io.BufferedWriter( |
|
|
new java.io.OutputStreamWriter(response.getOutputStream(), "GB18030"), |
|
|
|
|
|
|
|
|
new java.io.OutputStreamWriter(response.getOutputStream(), "GB18030"), |
|
|
8192 * 16); // 128KB缓冲区 |
|
|
8192 * 16); // 128KB缓冲区 |
|
|
|
|
|
|
|
|
try { |
|
|
try { |
|
|
@ -874,7 +894,7 @@ public class MesTidEpcLogServiceImpl extends ServiceImpl<MesTidEpcLogMapper, Mes |
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* @Description 写入方式4:CSV流式写入(边查边写,最高效)- rqrq |
|
|
* @Description 写入方式4:CSV流式写入(边查边写,最高效)- rqrq |
|
|
* |
|
|
|
|
|
|
|
|
* |
|
|
* <p><b>特点:</b></p> |
|
|
* <p><b>特点:</b></p> |
|
|
* <ul> |
|
|
* <ul> |
|
|
* <li>分批查询,每批查完立即写入CSV</li> |
|
|
* <li>分批查询,每批查完立即写入CSV</li> |
|
|
@ -882,7 +902,7 @@ public class MesTidEpcLogServiceImpl extends ServiceImpl<MesTidEpcLogMapper, Mes |
|
|
* <li>边查边写,总耗时最短</li> |
|
|
* <li>边查边写,总耗时最短</li> |
|
|
* </ul> |
|
|
* </ul> |
|
|
* <p><b>预计耗时:</b>50万条约25-30秒(查询+写入并行)</p> |
|
|
* <p><b>预计耗时:</b>50万条约25-30秒(查询+写入并行)</p> |
|
|
* |
|
|
|
|
|
|
|
|
* |
|
|
* @param data 查询条件 |
|
|
* @param data 查询条件 |
|
|
* @param dataTotal 数据总数(由调用方传入,避免重复COUNT查询) |
|
|
* @param dataTotal 数据总数(由调用方传入,避免重复COUNT查询) |
|
|
* @param response HttpServletResponse |
|
|
* @param response HttpServletResponse |
|
|
@ -976,17 +996,17 @@ public class MesTidEpcLogServiceImpl extends ServiceImpl<MesTidEpcLogMapper, Mes |
|
|
// ================================================================================== |
|
|
// ================================================================================== |
|
|
// ========================= 导出方法V1版本(备份,可随时切换)========================= |
|
|
// ========================= 导出方法V1版本(备份,可随时切换)========================= |
|
|
// ================================================================================== |
|
|
// ================================================================================== |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
/** |
|
|
* @Description 使用EasyExcel导出Excel文件(V1版本:分批查询分批写入)- rqrq |
|
|
* @Description 使用EasyExcel导出Excel文件(V1版本:分批查询分批写入)- rqrq |
|
|
* |
|
|
|
|
|
|
|
|
* |
|
|
* <p><b>【V1版本特点】</b></p> |
|
|
* <p><b>【V1版本特点】</b></p> |
|
|
* <ul> |
|
|
* <ul> |
|
|
* <li>每批查询10万条,查完立即写入Excel</li> |
|
|
* <li>每批查询10万条,查完立即写入Excel</li> |
|
|
* <li>优点:内存占用小,适合超大数据量</li> |
|
|
* <li>优点:内存占用小,适合超大数据量</li> |
|
|
* <li>缺点:IO操作频繁,可能较慢</li> |
|
|
* <li>缺点:IO操作频繁,可能较慢</li> |
|
|
* </ul> |
|
|
* </ul> |
|
|
* |
|
|
|
|
|
|
|
|
* |
|
|
* <p><b>【执行流程】</b></p> |
|
|
* <p><b>【执行流程】</b></p> |
|
|
* <ol> |
|
|
* <ol> |
|
|
* <li>先查询总数,计算需要查询的批次数</li> |
|
|
* <li>先查询总数,计算需要查询的批次数</li> |
|
|
@ -995,13 +1015,13 @@ public class MesTidEpcLogServiceImpl extends ServiceImpl<MesTidEpcLogMapper, Mes |
|
|
* <li>检查当前Sheet是否已满,满了则创建新Sheet</li> |
|
|
* <li>检查当前Sheet是否已满,满了则创建新Sheet</li> |
|
|
* <li>循环直到所有批次处理完成</li> |
|
|
* <li>循环直到所有批次处理完成</li> |
|
|
* </ol> |
|
|
* </ol> |
|
|
* |
|
|
|
|
|
|
|
|
* |
|
|
* <p><b>【切换方法】</b></p> |
|
|
* <p><b>【切换方法】</b></p> |
|
|
* <ol> |
|
|
* <ol> |
|
|
* <li>将Controller中调用的 exportCsv 改为 exportCsvOld</li> |
|
|
* <li>将Controller中调用的 exportCsv 改为 exportCsvOld</li> |
|
|
* <li>或者将本方法内容与 exportCsv 方法内容互换</li> |
|
|
* <li>或者将本方法内容与 exportCsv 方法内容互换</li> |
|
|
* </ol> |
|
|
* </ol> |
|
|
* |
|
|
|
|
|
|
|
|
* |
|
|
* @param data 查询条件 |
|
|
* @param data 查询条件 |
|
|
* @param response HttpServletResponse |
|
|
* @param response HttpServletResponse |
|
|
* @author rqrq |
|
|
* @author rqrq |
|
|
@ -1056,7 +1076,7 @@ public class MesTidEpcLogServiceImpl extends ServiceImpl<MesTidEpcLogMapper, Mes |
|
|
// 4.1 查询当前批次数据(手动分页,直接返回List)- rqrq |
|
|
// 4.1 查询当前批次数据(手动分页,直接返回List)- rqrq |
|
|
long offset = (long) (pageNum - 1) * pageSize; |
|
|
long offset = (long) (pageNum - 1) * pageSize; |
|
|
log.info("查询第 {}/{} 批,OFFSET: {} - rqrq", pageNum, totalPages, offset); |
|
|
log.info("查询第 {}/{} 批,OFFSET: {} - rqrq", pageNum, totalPages, offset); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 手动分页查询,无IPage开销 - rqrq |
|
|
// 手动分页查询,无IPage开销 - rqrq |
|
|
List<MesTidEpcLogExportData> records = mesTidEpcLogMapper.searchExportListManual(data, offset, pageSize); |
|
|
List<MesTidEpcLogExportData> records = mesTidEpcLogMapper.searchExportListManual(data, offset, pageSize); |
|
|
|
|
|
|
|
|
@ -1102,7 +1122,7 @@ public class MesTidEpcLogServiceImpl extends ServiceImpl<MesTidEpcLogMapper, Mes |
|
|
totalExported += exportList.size(); |
|
|
totalExported += exportList.size(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
log.info("已导出 {}/{} 条,当前Sheet {} 有 {} 条 - rqrq", |
|
|
|
|
|
|
|
|
log.info("已导出 {}/{} 条,当前Sheet {} 有 {} 条 - rqrq", |
|
|
totalExported, dataTotal, sheetIndex + 1, sheetRowCount); |
|
|
totalExported, dataTotal, sheetIndex + 1, sheetRowCount); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -1111,7 +1131,7 @@ public class MesTidEpcLogServiceImpl extends ServiceImpl<MesTidEpcLogMapper, Mes |
|
|
|
|
|
|
|
|
// ============ 步骤5:完成导出 ============ - rqrq |
|
|
// ============ 步骤5:完成导出 ============ - rqrq |
|
|
long endTime = System.currentTimeMillis(); |
|
|
long endTime = System.currentTimeMillis(); |
|
|
log.info("MES TID EPC日志导出完成(V1),共 {} 条,{} 个Sheet,总耗时: {} 秒 - rqrq", |
|
|
|
|
|
|
|
|
log.info("MES TID EPC日志导出完成(V1),共 {} 条,{} 个Sheet,总耗时: {} 秒 - rqrq", |
|
|
totalExported, sheetIndex + 1, (endTime - startTime) / 1000.0); |
|
|
totalExported, sheetIndex + 1, (endTime - startTime) / 1000.0); |
|
|
|
|
|
|
|
|
} catch (IOException e) { |
|
|
} catch (IOException e) { |
|
|
|