You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot生产环境下ActiveJDBC与MariaDB的重连处理方案

解决Spring Boot + ActiveJDBC 1.4.13数据库连接重连问题

老兄,我太懂这种生产环境的糟心问题了——应用先启动、数据库重启后连不上,老版本ActiveJDBC确实有这个连接重连的坑。既然你不想升级版本,那咱们就从现有版本的特性出发,给你几个靠谱的解决办法:

方案1:封装Base.open()实现重试逻辑

默认的Base.open()在数据库不可用时会直接抛出异常,不会自动重试。你可以写个工具类,给连接操作加上重试机制,不管是启动阶段还是后续遇到连接失效都能自动重试:

public class DBConnectionUtil {
    private static final int MAX_RETRIES = 5; // 最大重试次数
    private static final long RETRY_INTERVAL_MS = 3000; // 重试间隔(毫秒)

    public static void openWithRetry() throws InterruptedException {
        int retryCount = 0;
        while (retryCount < MAX_RETRIES) {
            try {
                // 从database.properties加载配置,和你原有逻辑一致
                Base.open(
                    getProperty("jdbc.driver"),
                    getProperty("jdbc.url"),
                    getProperty("jdbc.username"),
                    getProperty("jdbc.password")
                );
                System.out.println("数据库连接成功!");
                return;
            } catch (Exception e) {
                retryCount++;
                System.err.printf("连接失败,重试第%d次,原因:%s%n", retryCount, e.getMessage());
                Thread.sleep(RETRY_INTERVAL_MS);
            }
        }
        throw new RuntimeException("达到最大重试次数,无法建立数据库连接");
    }

    // 封装读取database.properties的方法
    private static String getProperty(String key) {
        Properties props = new Properties();
        try (InputStream is = DBConnectionUtil.class.getClassLoader().getResourceAsStream("database.properties")) {
            props.load(is);
            return props.getProperty(key);
        } catch (IOException e) {
            throw new RuntimeException("加载数据库配置失败", e);
        }
    }
}

之后启动时调用DBConnectionUtil.openWithRetry()替代直接Base.open();业务代码里如果捕获到连接失效异常,也可以调用这个方法重新建立连接。

方案2:用自定义连接池配置连接有效性校验

ActiveJDBC支持传入自定义DataSource,你可以用成熟的连接池(比如HikariCP),配置连接健康检查参数,让连接池自动剔除失效连接并创建新连接,比手动重试更可靠:

public class CustomDataSourceProvider {
    public static DataSource getValidatedDataSource() {
        HikariConfig config = new HikariConfig();
        // 从database.properties加载基础配置
        config.setJdbcUrl(getProperty("jdbc.url"));
        config.setUsername(getProperty("jdbc.username"));
        config.setPassword(getProperty("jdbc.password"));
        config.setDriverClassName(getProperty("jdbc.driver"));

        // 关键配置:开启连接有效性检查
        config.setConnectionTestQuery("SELECT 1"); // MariaDB通用校验语句
        config.setTestOnBorrow(true); // 获取连接时校验
        config.setValidationTimeout(5000); // 校验超时时间

        // 其他连接池优化参数(按需调整)
        config.setMaximumPoolSize(10);
        config.setConnectionTimeout(30000);
        config.setIdleTimeout(600000);

        return new HikariDataSource(config);
    }

    // 复用方案1的getProperty方法读取配置
    private static String getProperty(String key) {
        Properties props = new Properties();
        try (InputStream is = CustomDataSourceProvider.class.getClassLoader().getResourceAsStream("database.properties")) {
            props.load(is);
            return props.getProperty(key);
        } catch (IOException e) {
            throw new RuntimeException("加载数据库配置失败", e);
        }
    }
}

初始化连接时改用:

Base.open(CustomDataSourceProvider.getValidatedDataSource());

这样连接池会自动维护连接的健康状态,每次获取连接时都会校验有效性,失效的连接会被自动替换,不用你手动处理重连。

方案3:全局异常捕获触发重连

在业务代码的异常处理逻辑中,识别连接失效类的异常(比如包含Communications link failure的错误信息),主动关闭旧连接并触发重连:

public class DBExceptionHandler {
    public static void handleConnectionFailure(Exception e) {
        // 判断是否为连接失效异常
        if (e.getMessage() != null && e.getMessage().contains("Communications link failure")) {
            System.err.println("检测到数据库连接失效,尝试重新连接...");
            Base.close(); // 关闭失效的连接
            try {
                DBConnectionUtil.openWithRetry(); // 调用方案1的重试方法
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt();
                throw new RuntimeException("重连失败", ex);
            }
        }
        // 非连接异常直接抛出或处理
        throw new RuntimeException("数据库操作异常", e);
    }
}

然后在业务代码中使用:

try {
    // 数据库操作逻辑
    Base.open(); // 或用连接池方式
    // ...你的业务代码
} catch (Exception e) {
    DBExceptionHandler.handleConnectionFailure(e);
} finally {
    Base.close();
}

内容的提问来源于stack exchange,提问作者Marco Pantaleoni

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:30:45