在Java应用通过JDBC连接MySQL的场景中,自动重连机制可以有效降低连接断开对业务的影响,避免频繁手动重建连接带来的资源消耗和代码复杂度。实现该机制主要依赖JDBC连接URL的参数配置,同时可以结合连接池进一步优化重连效果。

JDBC自动重连的核心参数
MySQL的JDBC驱动(com.mysql.cj.jdbc.Driver)提供了多个和重连相关的参数,只需要在连接URL中配置即可开启对应能力,常用的参数如下:
- autoReconnect:是否开启自动重连,默认值为false,设置为true后驱动会在连接断开时尝试重新建立连接。
- autoReconnectForPools:针对连接池场景的自动重连开关,默认值为false,使用连接池时建议开启。
- maxReconnects:最大重连次数,默认值为3,超过该次数后重连失败会抛出异常。
- initialTimeout:首次重连前的等待时间,单位为秒,默认值为2。
- connectTimeout:建立连接的超时时间,单位为毫秒,默认值为0表示无超时限制。
- socketTimeout:socket读取的超时时间,单位为毫秒,默认值为0表示无超时限制。
基础自动重连实例
以下是一个不使用连接池,仅通过JDBC连接URL配置实现自动重连的代码示例:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class JdbcAutoReconnectDemo {
public static void main(String[] args) {
// JDBC连接URL,配置自动重连相关参数
String url = "jdbc:mysql://127.0.0.1:3306/test_db?useSSL=false&serverTimezone=UTC&autoReconnect=true&autoReconnectForPools=true&maxReconnects=5&initialTimeout=2&connectTimeout=3000&socketTimeout=5000";
String username = "root";
String password = "123456";
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
// 加载MySQL JDBC驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 获取数据库连接
conn = DriverManager.getConnection(url, username, password);
stmt = conn.createStatement();
// 执行查询语句
rs = stmt.executeQuery("SELECT VERSION()");
if (rs.next()) {
System.out.println("当前MySQL版本:" + rs.getString(1));
}
// 模拟连接断开后执行操作,驱动会自动尝试重连
// 实际场景中如果是网络波动导致连接断开,下一次执行SQL时会触发重连
rs = stmt.executeQuery("SELECT 1");
if (rs.next()) {
System.out.println("重连后查询结果:" + rs.getInt(1));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭资源
try {
if (rs != null) rs.close();
if (stmt != null) stmt.close();
if (conn != null) conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
结合连接池的自动重连实例
实际生产环境中通常会使用连接池管理数据库连接,以HikariCP为例,结合JDBC的自动重连参数可以实现更稳定的重连能力,配置和代码如下:
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
public class HikariAutoReconnectDemo {
public static void main(String[] args) {
HikariConfig config = new HikariConfig();
// 配置JDBC连接URL,包含自动重连参数
config.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/test_db?useSSL=false&serverTimezone=UTC&autoReconnect=true&maxReconnects=5&initialTimeout=2");
config.setUsername("root");
config.setPassword("123456");
// 连接池基础配置
config.setMaximumPoolSize(10);
config.setMinimumIdle(2);
// 连接超时时间,单位毫秒
config.setConnectionTimeout(3000);
// 连接最大存活时间,单位毫秒,避免连接长期不释放
config.setMaxLifetime(1800000);
// 连接测试查询,用于验证连接是否有效
config.setConnectionTestQuery("SELECT 1");
HikariDataSource dataSource = new HikariDataSource(config);
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
conn = dataSource.getConnection();
stmt = conn.createStatement();
rs = stmt.executeQuery("SELECT VERSION()");
if (rs.next()) {
System.out.println("连接池获取连接,MySQL版本:" + rs.getString(1));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (rs != null) rs.close();
if (stmt != null) stmt.close();
if (conn != null) conn.close();
} catch (Exception e) {
e.printStackTrace();
}
// 关闭连接池
dataSource.close();
}
}
}
注意事项
使用JDBC自动重连机制时需要注意以下几点:
- autoReconnect参数在MySQL JDBC驱动的高版本中部分场景已经被标记为不推荐,但是仍然可以正常使用,建议同时配合连接池的保活机制一起使用。
- 自动重连仅能处理连接断开的场景,如果数据库服务彻底不可用,多次重连失败后仍然会抛出异常,需要在业务层做好异常处理。
- 连接URL中的参数之间用&分隔,在Java字符串中需要转义为&,否则会出现语法错误。
- socketTimeout和connectTimeout需要根据实际业务场景设置合理的值,避免过短导致正常连接被误判为超时,或者过长导致业务阻塞。