864 lines
34 KiB
Java
864 lines
34 KiB
Java
package org.example;
|
||
|
||
import org.apache.poi.openxml4j.util.ZipSecureFile;
|
||
import org.apache.poi.ss.usermodel.Cell;
|
||
import org.apache.poi.ss.usermodel.Row;
|
||
import org.apache.poi.ss.usermodel.Sheet;
|
||
import org.apache.poi.ss.usermodel.Workbook;
|
||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||
|
||
import java.io.File;
|
||
import java.io.FileInputStream;
|
||
import java.sql.Connection;
|
||
import java.sql.PreparedStatement;
|
||
import java.sql.ResultSet;
|
||
import java.sql.Timestamp;
|
||
import java.util.ArrayList;
|
||
import java.util.List;
|
||
import java.util.UUID;
|
||
import java.util.regex.Matcher;
|
||
import java.util.regex.Pattern;
|
||
|
||
/**
|
||
* ---------纵断面数据导入器(根据实际Excel格式修正版)
|
||
*/
|
||
public class IaShzhVsurfaceDataImporter2 {
|
||
|
||
// 纵断面主表插入SQL
|
||
private static final String INSERT_VSURFACE_SQL =
|
||
"INSERT INTO SHZH_JCSJ.IA_M_VSURFACE " +
|
||
"(ZECD, ADCD, CHANNEL, ADDRESS, ISCTOWN, BASEELE, BASELGTD, BASELTTD, ELETYPE, " +
|
||
"METHOD, SIGNER, AUDID, STATUS, REMARK, MODITIME, ISENABLE, IMPORTYEAR, AUDBATCH, " +
|
||
"CADCD, GUID, INPUTTYPE, WSCD, SURFACE_CLASSIFY, OBJECT_NAME) " +
|
||
"VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||
|
||
// 纵断面点表插入SQL
|
||
private static final String INSERT_VSPOINT_SQL =
|
||
"INSERT INTO SHZH_JCSJ.IA_M_VSPOINT " +
|
||
"(ZSURFACEID, TRANSECTNAME, FID, POINT, DISTANCE, DIRECTION, HDEELE, SMEELE, " +
|
||
"LGTD, LTTD, MODITIME, REMARK, GUID, CHANNEL) " +
|
||
"VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
|
||
|
||
// 检查纵断面主表重复的SQL
|
||
private static final String CHECK_VSURFACE_DUPLICATE_SQL =
|
||
"SELECT COUNT(*) FROM SHZH_JCSJ.IA_M_VSURFACE WHERE ZECD = ? and SURFACE_CLASSIFY = ?";
|
||
|
||
// 检查纵断面点表重复的SQL
|
||
private static final String CHECK_VSPOINT_DUPLICATE_SQL =
|
||
"SELECT COUNT(*) FROM SHZH_JCSJ.IA_M_VSPOINT WHERE ZSURFACEID = ? AND FID = ?";
|
||
|
||
public static void main(String[] args) {
|
||
// 测试用的固定路径
|
||
// args = new String[]{"C:\\Users\\gsiot\\Desktop\\项目资料\\山洪\\小流域\\111"};
|
||
// args = new String[]{"F:\\1111-湖工大50条成果-已通过初检-待入库"};
|
||
// args = new String[]{"F:\\3333-2024年度咸宁市8条20251017-已通过初检-待入库"};
|
||
// args = new String[]{"F:\\4444-长江科学院-黄冈28条-已通过初检-已统一表头-待入库"};
|
||
|
||
args = new String[]{"C:\\Users\\gsiot\\Desktop\\项目资料\\山洪\\小流域\\111"};
|
||
if (args.length == 0) {
|
||
System.out.println("请提供湖工大9.29目录路径作为参数");
|
||
return;
|
||
}
|
||
|
||
String baseDir = args[0];
|
||
File baseDirectory = new File(baseDir);
|
||
|
||
if (!baseDirectory.exists() || !baseDirectory.isDirectory()) {
|
||
System.out.println("指定的目录不存在或不是有效目录: " + baseDir);
|
||
return;
|
||
}
|
||
|
||
System.out.println("开始处理目录: " + baseDir);
|
||
|
||
try {
|
||
processAllCounties(baseDirectory);
|
||
} catch (Exception e) {
|
||
System.err.println("处理过程中发生错误: " + e.getMessage());
|
||
e.printStackTrace();
|
||
}
|
||
}
|
||
|
||
private static void processAllCounties(File baseDir) {
|
||
File[] countyDirs = baseDir.listFiles(File::isDirectory);
|
||
if (countyDirs == null) {
|
||
System.out.println("在基础目录下未找到任何县市文件夹");
|
||
return;
|
||
}
|
||
|
||
int totalProcessed = 0;
|
||
int totalSuccess = 0;
|
||
int totalDuplicates = 0;
|
||
int totalPointDuplicates = 0;
|
||
|
||
System.out.println("找到 " + countyDirs.length + " 个县市文件夹");
|
||
|
||
for (File countyDir : countyDirs) {
|
||
String countyName = extractCountyName(countyDir.getName());
|
||
System.out.println("\n=== 处理县市: " + countyName + " ===");
|
||
|
||
try {
|
||
ProcessResult result = processCountyData(countyDir, countyName);
|
||
totalProcessed += result.processed;
|
||
totalDuplicates += result.duplicates;
|
||
totalPointDuplicates += result.pointDuplicates;
|
||
totalSuccess++;
|
||
System.out.println("✓ 成功处理 " + countyName +
|
||
",导入 " + result.processed + " 条记录,跳过 " + result.duplicates +
|
||
" 条重复记录,断面点跳过 " + result.pointDuplicates + " 条重复记录");
|
||
} catch (Exception e) {
|
||
System.err.println("✗ 处理县市 " + countyName + " 时出错: " + e.getMessage());
|
||
}
|
||
}
|
||
|
||
System.out.println("\n=== 处理完成 ===");
|
||
System.out.println("成功处理县市: " + totalSuccess + " 个");
|
||
System.out.println("总导入记录: " + totalProcessed + " 条");
|
||
System.out.println("纵断面主表跳过重复记录: " + totalDuplicates + " 条");
|
||
System.out.println("纵断面点表跳过重复记录: " + totalPointDuplicates + " 条");
|
||
}
|
||
|
||
private static ProcessResult processCountyData(File countyDir, String countyName) throws Exception {
|
||
int totalProcessed = 0;
|
||
int totalDuplicates = 0;
|
||
int totalPointDuplicates = 0;
|
||
|
||
// 查找小流域目录
|
||
File watershedDir = findWatershedDirectory(countyDir);
|
||
if (watershedDir == null) {
|
||
System.out.println("在 " + countyName + " 下未找到小流域目录");
|
||
return new ProcessResult(0, 0, 0);
|
||
}
|
||
System.out.println("找到小流域目录: " + watershedDir.getName());
|
||
|
||
// 查找所有水系目录
|
||
File[] sxDirs = findSxDirectories(watershedDir);
|
||
if (sxDirs == null || sxDirs.length == 0) {
|
||
System.out.println("在 " + watershedDir.getPath() + " 下未找到水系目录");
|
||
return new ProcessResult(0, 0, 0);
|
||
}
|
||
|
||
System.out.println("找到 " + sxDirs.length + " 个水系文件夹:");
|
||
for (File sxDir : sxDirs) {
|
||
System.out.println(" - " + sxDir.getName());
|
||
}
|
||
|
||
// 遍历处理每个水系文件夹
|
||
for (File sxDir : sxDirs) {
|
||
System.out.println("\n处理水系: " + sxDir.getName());
|
||
ProcessResult result = processSxData(sxDir, countyName);
|
||
totalProcessed += result.processed;
|
||
totalDuplicates += result.duplicates;
|
||
totalPointDuplicates += result.pointDuplicates;
|
||
System.out.println("水系 " + sxDir.getName() + " 导入 " + result.processed + " 条记录,跳过 " +
|
||
result.duplicates + " 条重复记录,断面点跳过 " + result.pointDuplicates + " 条重复记录");
|
||
}
|
||
|
||
return new ProcessResult(totalProcessed, totalDuplicates, totalPointDuplicates);
|
||
}
|
||
|
||
private static ProcessResult processSxData(File sxDir, String countyName) throws Exception {
|
||
int processedCount = 0;
|
||
int duplicateCount = 0;
|
||
int pointDuplicateCount = 0;
|
||
|
||
// 按照新的目录结构查找文件
|
||
File crossSectionDir = findCrossSectionDirectory(sxDir);
|
||
if (crossSectionDir == null) {
|
||
System.out.println("在 " + sxDir.getPath() + " 下未找到纵断面成果表目录");
|
||
return new ProcessResult(0, 0, 0);
|
||
}
|
||
System.out.println("找到纵断面成果表目录: " + crossSectionDir.getPath());
|
||
|
||
// 查找所有Excel文件
|
||
File[] excelFiles = findExcelFiles(crossSectionDir);
|
||
if (excelFiles == null || excelFiles.length == 0) {
|
||
System.out.println("在 " + crossSectionDir.getPath() + " 下未找到纵断面Excel文件");
|
||
return new ProcessResult(0, 0, 0);
|
||
}
|
||
|
||
System.out.println("找到 " + excelFiles.length + " 个纵断面Excel文件:");
|
||
for (File excelFile : excelFiles) {
|
||
System.out.println(" - " + excelFile.getName());
|
||
}
|
||
|
||
// 提取流域编码
|
||
String watershedCode = CommonUtils.extractWatershedCode(sxDir.getName());
|
||
System.out.println("流域编码: " + watershedCode);
|
||
|
||
// 处理每个Excel文件
|
||
for (File excelFile : excelFiles) {
|
||
System.out.println("\n处理文件: " + excelFile.getName());
|
||
try {
|
||
// 验证文件是否为有效Excel文件
|
||
if (!isValidExcelFile(excelFile)) {
|
||
System.err.println("跳过无效的Excel文件: " + excelFile.getName());
|
||
continue;
|
||
}
|
||
|
||
ProcessResult result = readExcelAndImport(excelFile, countyName, watershedCode);
|
||
processedCount += result.processed;
|
||
duplicateCount += result.duplicates;
|
||
pointDuplicateCount += result.pointDuplicates;
|
||
System.out.println("文件 " + excelFile.getName() + " 导入 " + result.processed +
|
||
" 条记录,跳过 " + result.duplicates + " 条重复记录");
|
||
} catch (Exception e) {
|
||
System.err.println("处理文件 " + excelFile.getName() + " 时出错: " + e.getMessage());
|
||
if (e.getMessage().contains("valid OOXML")) {
|
||
System.err.println(" 文件可能损坏或格式不正确,跳过此文件");
|
||
}
|
||
// 继续处理下一个文件
|
||
}
|
||
}
|
||
|
||
return new ProcessResult(processedCount, duplicateCount, pointDuplicateCount);
|
||
}
|
||
|
||
/**
|
||
* 验证文件是否为有效的Excel文件
|
||
*/
|
||
private static boolean isValidExcelFile(File file) {
|
||
if (!file.exists() || !file.isFile()) {
|
||
return false;
|
||
}
|
||
|
||
// 检查文件扩展名
|
||
String fileName = file.getName().toLowerCase();
|
||
if (!fileName.endsWith(".xlsx")) {
|
||
System.err.println("文件扩展名不是.xlsx: " + file.getName());
|
||
return false;
|
||
}
|
||
|
||
// 检查文件大小
|
||
if (file.length() == 0) {
|
||
System.err.println("文件大小为0: " + file.getName());
|
||
return false;
|
||
}
|
||
|
||
// 尝试打开文件验证格式
|
||
try (FileInputStream fis = new FileInputStream(file)) {
|
||
// 只读取文件头进行验证,不加载整个文件
|
||
byte[] header = new byte[4];
|
||
if (fis.read(header) != 4) {
|
||
return false;
|
||
}
|
||
// Excel文件的文件头特征
|
||
if (header[0] != 0x50 || header[1] != 0x4B || header[2] != 0x03 || header[3] != 0x04) {
|
||
System.err.println("文件头不符合Excel格式: " + file.getName());
|
||
return false;
|
||
}
|
||
return true;
|
||
} catch (Exception e) {
|
||
System.err.println("验证Excel文件失败: " + file.getName() + " - " + e.getMessage());
|
||
return false;
|
||
}
|
||
}
|
||
|
||
|
||
private static ProcessResult readExcelAndImport(File excelFile, String countyName, String wscd) throws Exception {
|
||
int importedCount = 0;
|
||
int duplicateCount = 0;
|
||
int pointDuplicateCount = 0;
|
||
|
||
// 先读取所有数据到内存
|
||
List<Object[]> vsurfaceDataList = new ArrayList<>();
|
||
List<Object[]> vspointDataList = new ArrayList<>();
|
||
|
||
readExcelData(wscd, excelFile, vsurfaceDataList, vspointDataList);
|
||
|
||
if (vsurfaceDataList.isEmpty()) {
|
||
System.out.println("未读取到有效数据");
|
||
return new ProcessResult(0, 0, 0);
|
||
}
|
||
|
||
System.out.println("成功读取 " + vsurfaceDataList.size() + " 条纵断面数据,包含 " +
|
||
vspointDataList.size() + " 个断面点,开始导入数据库...");
|
||
|
||
// 批量导入数据库
|
||
ProcessResult result = batchInsertData(vsurfaceDataList, vspointDataList);
|
||
return result;
|
||
}
|
||
|
||
private static void readExcelData(String wscd, File excelFile,
|
||
List<Object[]> vsurfaceDataList,
|
||
List<Object[]> vspointDataList) throws Exception {
|
||
|
||
// 保存原始设置
|
||
double originalRatio = ZipSecureFile.getMinInflateRatio();
|
||
|
||
try {
|
||
// 临时调整安全阈值
|
||
ZipSecureFile.setMinInflateRatio(0.001);
|
||
|
||
try (FileInputStream fis = new FileInputStream(excelFile);
|
||
Workbook workbook = new XSSFWorkbook(fis)) {
|
||
|
||
String surfaceClassify=excelFile.getName();
|
||
Pattern pattern = Pattern.compile("^[a-zA-Z0-9]+");
|
||
Matcher matcher = pattern.matcher(surfaceClassify);
|
||
if(matcher.find()){
|
||
surfaceClassify=matcher.group();
|
||
}else{
|
||
System.out.println("工作表表名有问题: " + surfaceClassify);
|
||
}
|
||
|
||
// 遍历所有工作表
|
||
for (int sheetIndex = 0; sheetIndex < workbook.getNumberOfSheets(); sheetIndex++) {
|
||
Sheet sheet = workbook.getSheetAt(sheetIndex);
|
||
String sheetName = sheet.getSheetName();
|
||
|
||
// 跳过填表说明等非数据工作表
|
||
if (sheetName.contains("填表说明") || sheetName.contains("说明")) {
|
||
continue;
|
||
}
|
||
|
||
System.out.println("处理工作表: " + sheetName);
|
||
|
||
try {
|
||
// 解析纵断面主表数据
|
||
Object[] vsurfaceData = parseVsurfaceData(sheet, sheetName, wscd, surfaceClassify);
|
||
if (vsurfaceData != null) {
|
||
vsurfaceDataList.add(vsurfaceData);
|
||
System.out.println("✓ 解析纵断面主表数据成功: " + sheetName);
|
||
|
||
// 解析断面点数据
|
||
List<Object[]> points = parseVspointData(sheet, (String) vsurfaceData[19]);
|
||
vspointDataList.addAll(points);
|
||
System.out.println("✓ 解析 " + points.size() + " 个断面点数据");
|
||
}
|
||
} catch (Exception e) {
|
||
System.err.println("解析工作表 " + sheetName + " 时出错: " + e.getMessage());
|
||
}
|
||
}
|
||
}
|
||
} finally {
|
||
// 恢复原始设置
|
||
ZipSecureFile.setMinInflateRatio(originalRatio);
|
||
}
|
||
}
|
||
|
||
private static Object[] parseVsurfaceData(Sheet sheet, String sheetName, String wscd, String surfaceClassify) {
|
||
try {
|
||
Object[] data = new Object[24]; // 对应24个插入参数
|
||
|
||
int index = 0;
|
||
|
||
// 根据Excel格式解析数据
|
||
// 第1行:C列-所在位置
|
||
String location = getCellValue(sheet, 0, 2); // C1单元格
|
||
|
||
// 第2行:C列-所在沟道,G列-行政区划代码
|
||
String channel = getCellValue(sheet, 1, 2); // C2单元格
|
||
String adminCode = getCellValue(sheet, 1, 6); // G2单元格
|
||
|
||
// 第3行:C列-是否跨县
|
||
String isCrossCounty = getCellValue(sheet, 2, 2); // C3单元格
|
||
|
||
// 第4行:C列-控制点纬度,G列-控制点高程
|
||
String baseLatitude = getCellValue(sheet, 3, 2); // C4单元格 - 控制点纬度
|
||
String baseElevation = getCellValue(sheet, 3, 6); // G4单元格 - 控制点高程
|
||
|
||
// 第5行:C列-高程系,G列-测量方法
|
||
String elevationType = getCellValue(sheet, 4, 2); // C5单元格 - 高程系
|
||
String method = getCellValue(sheet, 4, 6); // G5单元格 - 测量方法
|
||
|
||
// 控制点经度(在Excel中没有明确位置,设为空)
|
||
String baseLongitude = null;
|
||
|
||
// 1. ZECD - 纵断面编码 (工作表名)
|
||
data[index++] = sheetName;
|
||
|
||
// 2. ADCD - 行政区划代码
|
||
data[index++] = getSafeString(adminCode);
|
||
|
||
// 3. CHANNEL - 所在沟道
|
||
data[index++] = getSafeString(channel);
|
||
|
||
// 4. ADDRESS - 所在位置
|
||
data[index++] = getSafeString(location);
|
||
|
||
// 5. ISCTOWN - 是否跨县
|
||
data[index++] = getSafeString(isCrossCounty);
|
||
|
||
// 6. BASEELE - 控制点高程
|
||
data[index++] = getSafeString(baseElevation);
|
||
|
||
// 7. BASELGTD - 控制点经度
|
||
data[index++] = getSafeString(baseLongitude);
|
||
|
||
// 8. BASELTTD - 控制点纬度
|
||
data[index++] = getSafeString(baseLatitude);
|
||
|
||
// 9. ELETYPE - 高程系
|
||
data[index++] = getSafeString(elevationType);
|
||
|
||
// 10. METHOD - 测量方法
|
||
data[index++] = getSafeString(method);
|
||
|
||
// 11. SIGNER - 填写人姓名(默认为空)
|
||
data[index++] = null;
|
||
|
||
// 12. AUDID - 审核批次号(默认为空)
|
||
data[index++] = null;
|
||
|
||
// 13. STATUS - 状态(默认1-待审核)
|
||
data[index++] = "1";
|
||
|
||
// 14. REMARK - 备注
|
||
data[index++] = null;
|
||
|
||
// 15. MODITIME - 时间戳
|
||
data[index++] = new Timestamp(System.currentTimeMillis());
|
||
|
||
// 16. ISENABLE - 启用状态
|
||
data[index++] = "1";
|
||
|
||
// 17. IMPORTYEAR - 导入年份
|
||
data[index++] = "2025";
|
||
|
||
// 18. AUDBATCH - 审核批次
|
||
data[index++] = "BATCH_" + System.currentTimeMillis();
|
||
|
||
// 19. CADCD - 县级编码(从行政区划代码提取)
|
||
data[index++] = adminCode != null && adminCode.length() >= 6 ?
|
||
adminCode.substring(0, 6)+"000000000" : "";
|
||
|
||
// 20. GUID - 唯一标识
|
||
String guid = UUID.randomUUID().toString();
|
||
data[index++] = guid;
|
||
|
||
// 21. INPUTTYPE - 录入方式
|
||
data[index++] = "1";
|
||
|
||
// 22. WSCD - 流域编码
|
||
data[index++] = wscd;
|
||
|
||
// 23. SURFACE_CLASSIFY - 断面分类
|
||
data[index++] = surfaceClassify;
|
||
|
||
// 24. OBJECT_NAME - 对象名称(使用沟道名称)
|
||
data[index++] = null;
|
||
|
||
return data;
|
||
|
||
} catch (Exception e) {
|
||
System.err.println("解析纵断面主表数据失败: " + e.getMessage());
|
||
e.printStackTrace();
|
||
return null;
|
||
}
|
||
}
|
||
|
||
private static List<Object[]> parseVspointData(Sheet sheet, String vsurfaceId) {
|
||
List<Object[]> points = new ArrayList<>();
|
||
|
||
try {
|
||
// 找到数据开始行(从第7行开始,序号列开始)
|
||
int startRow = 6; // 根据Excel格式,数据从第7行开始
|
||
System.out.println("断面点数据从第 " + (startRow + 1) + " 行开始");
|
||
|
||
for (int i = startRow; i <= sheet.getLastRowNum(); i++) {
|
||
Row row = sheet.getRow(i);
|
||
if (row == null) continue;
|
||
|
||
// 检查序号列是否为空
|
||
Cell serialCell = row.getCell(0);
|
||
if (serialCell == null || isCellEmpty(serialCell)) {
|
||
continue;
|
||
}
|
||
|
||
Object[] pointData = parseVspointRowData(row, vsurfaceId, i - startRow + 1);
|
||
if (pointData != null) {
|
||
points.add(pointData);
|
||
}
|
||
}
|
||
|
||
} catch (Exception e) {
|
||
System.err.println("解析断面点数据失败: " + e.getMessage());
|
||
e.printStackTrace();
|
||
}
|
||
|
||
return points;
|
||
}
|
||
|
||
private static Object[] parseVspointRowData(Row row, String vsurfaceId, int fid) {
|
||
try {
|
||
Object[] data = new Object[14]; // 对应14个插入参数
|
||
|
||
int index = 0;
|
||
|
||
// 1. ZSURFACEID - 纵断面主表ID
|
||
data[index++] = vsurfaceId;
|
||
|
||
// 2. TRANSECTNAME - 断面名称(使用测量点)
|
||
String measurePoint = getCellStringValue(row.getCell(1));
|
||
data[index++] = getSafeString(measurePoint);
|
||
|
||
// 3. FID - 断面序号
|
||
data[index++] = fid;
|
||
|
||
// 4. POINT - 断面信息-测量点
|
||
data[index++] = getSafeString(measurePoint);
|
||
|
||
// 5. DISTANCE - 断面信息-距离(m) - 第3列
|
||
data[index++] = parseDoubleWithDefault(getCellStringValue(row.getCell(2)));
|
||
|
||
// 6. DIRECTION - 量距方向(°) - 第4列
|
||
data[index++] = parseDoubleWithDefault(getCellStringValue(row.getCell(3)));
|
||
|
||
// 7. HDEELE - 断面信息-河底高程(m) - 第5列
|
||
data[index++] = parseDoubleWithDefault(getCellStringValue(row.getCell(4)));
|
||
|
||
// 8. SMEELE - 断面信息-水面高程(m) - 第6列
|
||
data[index++] = parseDoubleWithDefault(getCellStringValue(row.getCell(5)));
|
||
|
||
// 9. LGTD - 经度(°) - 第7列
|
||
data[index++] = parseDoubleWithDefault(getCellStringValue(row.getCell(6)));
|
||
|
||
// 10. LTTD - 纬度(°) - 第8列
|
||
data[index++] = parseDoubleWithDefault(getCellStringValue(row.getCell(7)));
|
||
|
||
// 11. MODITIME - 时间戳
|
||
data[index++] = new Timestamp(System.currentTimeMillis());
|
||
|
||
// 12. REMARK - 备注
|
||
data[index++] = null;
|
||
|
||
// 13. GUID - 唯一标识
|
||
data[index++] = UUID.randomUUID().toString();
|
||
|
||
// 14. CHANNEL - 量距方向(°) - 使用第4列的值
|
||
data[index++] = parseDoubleWithDefault(getCellStringValue(row.getCell(3)));
|
||
|
||
return data;
|
||
|
||
} catch (Exception e) {
|
||
System.err.println("解析断面点行数据失败: " + e.getMessage());
|
||
return null;
|
||
}
|
||
}
|
||
|
||
private static ProcessResult batchInsertData(List<Object[]> vsurfaceDataList, List<Object[]> vspointDataList) {
|
||
int importedCount = 0;
|
||
int duplicateCount = 0;
|
||
int pointDuplicateCount = 0;
|
||
|
||
Connection conn = null;
|
||
PreparedStatement vsurfacePstmt = null;
|
||
PreparedStatement vspointPstmt = null;
|
||
PreparedStatement checkVsurfaceDupPstmt = null;
|
||
PreparedStatement checkVspointDupPstmt = null;
|
||
|
||
try {
|
||
conn = DatabaseUtil.getConnection();
|
||
if (conn == null) {
|
||
System.err.println("无法获取数据库连接");
|
||
return new ProcessResult(0, 0, 0);
|
||
}
|
||
|
||
vsurfacePstmt = conn.prepareStatement(INSERT_VSURFACE_SQL);
|
||
vspointPstmt = conn.prepareStatement(INSERT_VSPOINT_SQL);
|
||
checkVsurfaceDupPstmt = conn.prepareStatement(CHECK_VSURFACE_DUPLICATE_SQL);
|
||
checkVspointDupPstmt = conn.prepareStatement(CHECK_VSPOINT_DUPLICATE_SQL);
|
||
|
||
conn.setAutoCommit(false); // 开启事务
|
||
|
||
// 处理纵断面主表数据
|
||
for (Object[] rowData : vsurfaceDataList) {
|
||
try {
|
||
String zecd = (String) rowData[0];
|
||
String surface_clasify = (String) rowData[22];
|
||
// 检查纵断面是否重复
|
||
checkVsurfaceDupPstmt.setString(1, zecd);
|
||
checkVsurfaceDupPstmt.setString(2, surface_clasify);
|
||
try (ResultSet rs = checkVsurfaceDupPstmt.executeQuery()) {
|
||
if (rs.next() && rs.getInt(1) > 0) {
|
||
duplicateCount++;
|
||
System.out.println("跳过重复纵断面: " + zecd);
|
||
continue;
|
||
}
|
||
}
|
||
|
||
// 插入数据 - 设置所有参数
|
||
setVsurfaceParameters(vsurfacePstmt, rowData);
|
||
vsurfacePstmt.executeUpdate();
|
||
importedCount++;
|
||
System.out.println("✓ 插入纵断面记录: " + zecd);
|
||
|
||
} catch (Exception e) {
|
||
System.err.println("纵断面数据插入失败: " + e.getMessage());
|
||
e.printStackTrace();
|
||
}
|
||
}
|
||
|
||
// 处理纵断面点表数据
|
||
int pointImportedCount = 0;
|
||
for (Object[] pointData : vspointDataList) {
|
||
try {
|
||
String vsurfaceId = (String) pointData[0];
|
||
Integer fid = (Integer) pointData[2];
|
||
|
||
// 检查断面点是否重复
|
||
checkVspointDupPstmt.setString(1, vsurfaceId);
|
||
checkVspointDupPstmt.setInt(2, fid);
|
||
try (ResultSet rs = checkVspointDupPstmt.executeQuery()) {
|
||
if (rs.next() && rs.getInt(1) > 0) {
|
||
pointDuplicateCount++;
|
||
continue;
|
||
}
|
||
}
|
||
|
||
// 插入数据 - 设置所有参数
|
||
setVspointParameters(vspointPstmt, pointData);
|
||
vspointPstmt.addBatch();
|
||
pointImportedCount++;
|
||
|
||
// 每10条执行一次批量插入
|
||
if (pointImportedCount % 10 == 0) {
|
||
vspointPstmt.executeBatch();
|
||
vspointPstmt.clearBatch(); // 清空批量
|
||
System.out.println("已批量插入 " + pointImportedCount + " 条断面点记录");
|
||
}
|
||
|
||
} catch (Exception e) {
|
||
System.err.println("断面点数据插入失败: " + e.getMessage());
|
||
e.printStackTrace();
|
||
}
|
||
}
|
||
|
||
// 执行剩余的断面点批量插入
|
||
if (pointImportedCount > 0) {
|
||
vspointPstmt.executeBatch();
|
||
System.out.println("最终批量插入完成,共 " + pointImportedCount + " 条断面点记录");
|
||
}
|
||
|
||
conn.commit(); // 提交事务
|
||
System.out.println("事务提交成功");
|
||
|
||
} catch (Exception e) {
|
||
System.err.println("批量插入数据失败: " + e.getMessage());
|
||
e.printStackTrace();
|
||
if (conn != null) {
|
||
try {
|
||
conn.rollback();
|
||
System.out.println("事务回滚成功");
|
||
} catch (Exception rollbackEx) {
|
||
System.err.println("事务回滚失败: " + rollbackEx.getMessage());
|
||
}
|
||
}
|
||
} finally {
|
||
// 关闭资源
|
||
closeResource(checkVspointDupPstmt);
|
||
closeResource(checkVsurfaceDupPstmt);
|
||
closeResource(vspointPstmt);
|
||
closeResource(vsurfacePstmt);
|
||
closeResource(conn);
|
||
}
|
||
|
||
return new ProcessResult(importedCount, duplicateCount, pointDuplicateCount);
|
||
}
|
||
|
||
// 设置纵断面主表参数
|
||
private static void setVsurfaceParameters(PreparedStatement pstmt, Object[] rowData) throws Exception {
|
||
for (int i = 0; i < rowData.length; i++) {
|
||
Object value = rowData[i];
|
||
if (value == null) {
|
||
pstmt.setNull(i + 1, java.sql.Types.NULL);
|
||
} else if (value instanceof String) {
|
||
pstmt.setString(i + 1, (String) value);
|
||
} else if (value instanceof Double) {
|
||
pstmt.setDouble(i + 1, (Double) value);
|
||
} else if (value instanceof Integer) {
|
||
pstmt.setInt(i + 1, (Integer) value);
|
||
} else if (value instanceof Timestamp) {
|
||
pstmt.setTimestamp(i + 1, (Timestamp) value);
|
||
} else {
|
||
pstmt.setObject(i + 1, value);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 设置纵断面点表参数
|
||
private static void setVspointParameters(PreparedStatement pstmt, Object[] pointData) throws Exception {
|
||
for (int i = 0; i < pointData.length; i++) {
|
||
Object value = pointData[i];
|
||
if (value == null) {
|
||
pstmt.setNull(i + 1, java.sql.Types.NULL);
|
||
} else if (value instanceof String) {
|
||
pstmt.setString(i + 1, (String) value);
|
||
} else if (value instanceof Double) {
|
||
pstmt.setDouble(i + 1, (Double) value);
|
||
} else if (value instanceof Integer) {
|
||
pstmt.setInt(i + 1, (Integer) value);
|
||
} else if (value instanceof Timestamp) {
|
||
pstmt.setTimestamp(i + 1, (Timestamp) value);
|
||
} else {
|
||
pstmt.setObject(i + 1, value);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 安全关闭资源的方法
|
||
private static void closeResource(AutoCloseable resource) {
|
||
if (resource != null) {
|
||
try {
|
||
resource.close();
|
||
} catch (Exception e) {
|
||
System.err.println("关闭资源时出错: " + e.getMessage());
|
||
}
|
||
}
|
||
}
|
||
|
||
// 辅助方法:安全获取字符串,避免null
|
||
private static String getSafeString(String value) {
|
||
return value != null ? value : "";
|
||
}
|
||
|
||
// 辅助方法:解析Double,提供默认值
|
||
private static Double parseDoubleWithDefault(String value) {
|
||
if (value != null && !value.trim().isEmpty()) {
|
||
try {
|
||
return Double.parseDouble(value.trim());
|
||
} catch (NumberFormatException e) {
|
||
return 0.0;
|
||
}
|
||
}
|
||
return 0.0;
|
||
}
|
||
|
||
// 辅助方法
|
||
private static class ProcessResult {
|
||
int processed;
|
||
int duplicates;
|
||
int pointDuplicates;
|
||
|
||
ProcessResult(int processed, int duplicates, int pointDuplicates) {
|
||
this.processed = processed;
|
||
this.duplicates = duplicates;
|
||
this.pointDuplicates = pointDuplicates;
|
||
}
|
||
}
|
||
|
||
// 目录查找方法(保持不变)
|
||
private static File findWatershedDirectory(File countyDir) {
|
||
File[] subDirs = countyDir.listFiles(File::isDirectory);
|
||
if (subDirs != null) {
|
||
for (File subDir : subDirs) {
|
||
if (subDir.getName().contains("小流域")) {
|
||
return subDir;
|
||
}
|
||
}
|
||
if (subDirs.length > 0) return subDirs[0];
|
||
}
|
||
return null;
|
||
}
|
||
|
||
private static File[] findSxDirectories(File watershedDir) {
|
||
File[] subDirs = watershedDir.listFiles(File::isDirectory);
|
||
if (subDirs != null) {
|
||
List<File> sxDirs = new ArrayList<>();
|
||
for (File subDir : subDirs) {
|
||
if (subDir.getName().contains("水系") || subDir.getName().matches("^HBWFF.*")) {
|
||
sxDirs.add(subDir);
|
||
}
|
||
}
|
||
return sxDirs.toArray(new File[0]);
|
||
}
|
||
return null;
|
||
}
|
||
|
||
private static File findCrossSectionDirectory(File sxDir) {
|
||
// 按照新目录结构:水系目录 > 电子数据 > 测量数据 > 防治对象断面成果 > 纵断面成果表
|
||
File electronicDataDir = findSubDirectory(sxDir, "电子数据");
|
||
if (electronicDataDir == null) {
|
||
System.out.println("在 " + sxDir.getPath() + " 下未找到电子数据目录");
|
||
return null;
|
||
}
|
||
|
||
File measureDataDir = findSubDirectory(electronicDataDir, "测量数据");
|
||
if (measureDataDir == null) {
|
||
System.out.println("在 " + electronicDataDir.getPath() + " 下未找到测量数据目录");
|
||
return null;
|
||
}
|
||
|
||
File sectionResultDir = findSubDirectory(measureDataDir, "防治对象断面成果");
|
||
if (sectionResultDir == null) {
|
||
System.out.println("在 " + measureDataDir.getPath() + " 下未找到防治对象断面成果目录");
|
||
return null;
|
||
}
|
||
|
||
File crossSectionDir = findSubDirectory(sectionResultDir, "纵断面成果表");
|
||
if (crossSectionDir == null) {
|
||
System.out.println("在 " + sectionResultDir.getPath() + " 下未找到纵断面成果表目录");
|
||
return null;
|
||
}
|
||
|
||
return crossSectionDir;
|
||
}
|
||
|
||
private static File findSubDirectory(File parentDir, String dirName) {
|
||
File[] subDirs = parentDir.listFiles(File::isDirectory);
|
||
if (subDirs != null) {
|
||
for (File subDir : subDirs) {
|
||
if (subDir.getName().equals(dirName)) {
|
||
return subDir;
|
||
}
|
||
}
|
||
// 如果没有精确匹配,尝试包含匹配
|
||
for (File subDir : subDirs) {
|
||
if (subDir.getName().contains(dirName)) {
|
||
return subDir;
|
||
}
|
||
}
|
||
}
|
||
return null;
|
||
}
|
||
|
||
private static File[] findExcelFiles(File crossSectionDir) {
|
||
File[] files = crossSectionDir.listFiles((dir, name) ->
|
||
name.toLowerCase().endsWith(".xlsx"));
|
||
return files != null ? files : new File[0];
|
||
}
|
||
|
||
private static String extractCountyName(String dirName) {
|
||
return dirName.contains("、") ? dirName.split("、")[1].trim() : dirName;
|
||
}
|
||
|
||
private static String getCellValue(Sheet sheet, int rowNum, int colNum) {
|
||
Row row = sheet.getRow(rowNum);
|
||
if (row != null) {
|
||
Cell cell = row.getCell(colNum);
|
||
return getCellStringValue(cell);
|
||
}
|
||
return null;
|
||
}
|
||
|
||
private static String getCellStringValue(Cell cell) {
|
||
if (cell == null) return null;
|
||
try {
|
||
switch (cell.getCellType()) {
|
||
case STRING:
|
||
return cell.getStringCellValue().trim();
|
||
case NUMERIC:
|
||
double num = cell.getNumericCellValue();
|
||
return (num == (long) num) ? String.valueOf((long) num) : String.valueOf(num);
|
||
case BOOLEAN:
|
||
return String.valueOf(cell.getBooleanCellValue());
|
||
default:
|
||
return null;
|
||
}
|
||
} catch (Exception e) {
|
||
return null;
|
||
}
|
||
}
|
||
|
||
private static boolean isCellEmpty(Cell cell) {
|
||
if (cell == null) return true;
|
||
switch (cell.getCellType()) {
|
||
case BLANK:
|
||
return true;
|
||
case STRING:
|
||
return cell.getStringCellValue().trim().isEmpty();
|
||
default:
|
||
return false;
|
||
}
|
||
}
|
||
} |