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
相关产品推荐
相关产品推荐

