import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.sql.Connection; import java.sql.DriverManager; import java.sql.Statement; import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.regex.Pattern; /** * 执行 sql/ 目录下的脚本(按 GO 分批),用于建表 / 索引 / 视图。 * * 用法(在 fms-api 目录下运行): * java -cp "tools/migration/mssql-jdbc-13.4.0.jre11.jar" tools/migration/RunSqlFile.java [--dry-run] * * 说明: * - 目标库固定取 config/dbconfigs/G3HD.properties,执行前校验 catalog 必须是 FMS。 * - 含「重建」段落(drop ... if exists)的脚本请确认表数据已不需要后再执行。 * - DDL 在单个事务中执行,任一批次失败整体回滚。 */ public final class RunSqlFile { private static final Pattern GO = Pattern.compile("(?im)^\\s*GO\\s*;?\\s*$"); public static void main(String[] args) throws Exception { if (args.length < 1) { System.out.println("用法: RunSqlFile [--dry-run]"); return; } Path script = Path.of(args[0]).toAbsolutePath().normalize(); boolean dryRun = args.length > 1 && "--dry-run".equalsIgnoreCase(args[1]); Path apiRoot = Path.of("").toAbsolutePath().normalize(); Properties properties = new Properties(); try (InputStream input = Files.newInputStream(apiRoot.resolve("config/dbconfigs/G3HD.properties"))) { properties.load(input); } List batches = new ArrayList<>(); for (String batch : GO.split(Files.readString(script, StandardCharsets.UTF_8))) { String trimmed = batch.trim(); if (!trimmed.isEmpty()) { batches.add(trimmed); } } System.out.println("脚本: " + script); System.out.println("批次: " + batches.size() + (dryRun ? "(dry-run,不执行)" : "")); for (String batch : batches) { System.out.println(" - " + firstLine(batch)); } if (dryRun) { return; } try (Connection connection = DriverManager.getConnection( properties.getProperty("url"), properties.getProperty("username"), properties.getProperty("password"))) { if (!"FMS".equalsIgnoreCase(connection.getCatalog())) { throw new IllegalStateException("Refusing to run on database: " + connection.getCatalog()); } connection.setAutoCommit(false); int applied = 0; try { for (String batch : batches) { try (Statement statement = connection.createStatement()) { statement.execute(batch); } applied++; System.out.println("APPLIED|" + firstLine(batch)); } connection.commit(); } catch (Exception e) { connection.rollback(); throw new IllegalStateException("第 " + (applied + 1) + " 批失败,已回滚: " + e.getMessage(), e); } System.out.println("OK|batches=" + applied); } } private static String firstLine(String batch) { for (String line : batch.split("\\R")) { String trimmed = line.trim(); if (!trimmed.isEmpty() && !trimmed.startsWith("--") && !trimmed.startsWith("/*")) { return trimmed.length() > 90 ? trimmed.substring(0, 90) + "..." : trimmed; } } return batch.split("\\R")[0].trim(); } }