liu
2026-10-30 dd1a51612fcd3c839d31dfa0df83b3d3071c8145
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
 
/**
 * 无人值守升级脚本执行器。直接读取 application-tide.yml 中的主库配置,
 * 避免在命令行、日志或临时文件中复制数据库口令。
 */
public class DatabaseUpgrade {
    public static void main(String[] args) throws Exception {
        String config = args.length > 0 ? args[0] : "src/main/resources/application-tide.yml";
        String script = args.length > 1 ? args[1] : "doc/unattended_upgrade.sql";
        List<String> yaml = Files.readAllLines(Paths.get(config), StandardCharsets.UTF_8);
        String url = firstValue(yaml, "url: jdbc:mysql:");
        String username = valueAfter(yaml, "url: jdbc:mysql:", "username:");
        String password = valueAfter(yaml, "url: jdbc:mysql:", "password:");
        if (url == null || username == null) throw new IllegalStateException("未找到主数据库配置");
 
        Class.forName("com.mysql.cj.jdbc.Driver");
        try (Connection connection = DriverManager.getConnection(url, username, password);
             Statement statement = connection.createStatement()) {
            int count = 0;
            for (String sql : splitSql(Files.readAllLines(Paths.get(script), StandardCharsets.UTF_8))) {
                if (!sql.trim().isEmpty()) {
                    statement.execute(sql);
                    count++;
                }
            }
            System.out.println("无人值守数据库升级完成,共执行 " + count + " 条语句。");
        }
    }
 
    private static String firstValue(List<String> lines, String marker) {
        for (String line : lines) if (line.trim().startsWith(marker)) return line.trim().substring(5).trim();
        return null;
    }
 
    private static String valueAfter(List<String> lines, String anchor, String key) {
        boolean found = false;
        for (String line : lines) {
            String value = line.trim();
            if (value.startsWith(anchor)) found = true;
            else if (found && value.startsWith(key)) return value.substring(key.length()).trim();
        }
        return null;
    }
 
    private static List<String> splitSql(List<String> lines) {
        List<String> result = new ArrayList<>();
        String delimiter = ";";
        StringBuilder current = new StringBuilder();
        for (String line : lines) {
            String trimmed = line.trim();
            if (trimmed.startsWith("--") || trimmed.isEmpty()) continue;
            if (trimmed.toUpperCase().startsWith("DELIMITER ")) {
                delimiter = trimmed.substring("DELIMITER ".length()).trim();
                continue;
            }
            current.append(line).append('\n');
            if (trimmed.endsWith(delimiter)) {
                int end = current.length() - delimiter.length() - 1;
                result.add(current.substring(0, Math.max(0, end)).trim());
                current.setLength(0);
            }
        }
        if (current.length() > 0) result.add(current.toString().trim());
        return result;
    }
}