带自动重新连接的 JDBC 连接

Posted

技术标签:

【中文标题】带自动重新连接的 JDBC 连接【英文标题】:JDBC connection with auto reconnect 【发布时间】:2010-12-06 11:40:31 【问题描述】:

我正在使用 JDBC 连接到数据库服务器。 连接是通过无线网络进行的,有时可能很狡猾。 在连接丢失的那一刻,我需要关闭并重新启动应用程序。

有没有人有一些代码示例,我可以在其中编写某种包装器来自动重新连接并重新运行最后一个查询?这样可以省去很多麻烦。

我只是不确定应该/可以如何实施。 也许已经有可用的东西了?

【问题讨论】:

【参考方案1】:

查看 Oracle 的通用连接池 (UCP) 库。它们完全符合 JDBC 4.0 并实现 isValid() 调用以检查连接是否处于活动状态。执行此检查很容易,如果错误重新连接,则运行您的查询。

Oracle UCP Download Page

虽然我知道您没有询问连接池,但您可能还是应该使用连接池,所以这将对您有双重帮助。

【讨论】:

OP正在使用Firebird,他为什么要使用Oracle的驱动程序?然后,我不会在我的代码中实现连接验证逻辑,我宁愿使用一个实现此检查的池(并且不需要为此使用 JDBC 4.0 驱动程序)。 假设 Firebird(我承认我对它的了解为零)有一个 JDBC 驱动程序,那么他仍然可以使用这些类。请注意,它们被称为通用连接池——它是 Oracle 的 C3P0 或 Proxool 版本。它们适用于任何 JDBC 驱动程序。是的,这个池会自己做验证逻辑。 我同意“通用”连接池。但是,“符合 JBDC 4.0”是指 JDBC 驱动程序(这次是 Oracle 特定的),而不是池。这就是我的观点。 但是 UCP 使用 JDBC 4.0 的特性(特别是 java.sql.PooledConnection 类中的新 isValid() 调用)来进行一些验证。如果驱动程序不兼容 4.0,我认为池的所有功能都不会起作用。但是是的,您始终可以自己进行检查,或者它可能会为其他驱动程序提供另一种验证机制。 你能提供一个参考吗?据我所知,Jaybird 是一个 JDBC 2.0 驱动程序,因此了解在使用 Oracle 的 UCP 时什么会起作用会很有趣。顺便说一句,我注意到 UCP 提供了oracle.ucp.jdbc.ValidConnection,但是,TBH,我不认为使用供应商特定的类是一个好主意,也不推荐它。【参考方案2】:

让连接池为您处理这个问题,其中许多可以验证连接。 DBCP 也是如此,它有一个 testOnBorrow 参数,在使用之前强制对每个连接进行完整性检查。该参数的默认值为true,只需将validationQuery设置为非空字符串即可生效。所以设置validationQuery 就可以了!查看documentation。

【讨论】:

【参考方案3】:

即使您使用应用程序服务器提供的 JDBC 连接池或 apache 公共池,编写重试逻辑也是值得的。根据您的应用程序服务器的配置,应用程序服务器将清除所有池连接并重新创建一组新连接。这是一个示例:

Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
//
// How many times do you want to retry the transaction
// (or at least _getting_ a connection)?
//
int retryCount = 5;
boolean transactionCompleted = false;
do 

  try 
    conn = getConnection(); // assume getting this from a
    // javax.sql.DataSource, or the
    // java.sql.DriverManager

    retryCount = 0;
    stmt = conn.createStatement();
    String query = "Some sample SQL";
    rs = stmt.executeQuery(query);
    while (rs.next()) 
    
    rs.close();
    rs = null;
    stmt.close();
    stmt = null;

    conn.close();
    conn = null;
    transactionCompleted = true;
   catch (SQLException sqlEx) 
    //
    // The two SQL states that are 'retry-able' 
    // for a communications error.
    //
    // Only retry if the error was due to a stale connection,
    // communications problem 
    //
    String sqlState = sqlEx.getSQLState();
    if ("Substitute with Your DB documented sqlstate number for stale connection".equals(sqlState) ) 
      retryCount--;
     else 
      retryCount = 0;
    
   finally 
    if (rs != null) 
      try 
        rs.close();
       catch (SQLException sqlEx) 
        // log this
      
    
    if (stmt != null) 
      try 
        stmt.close();
       catch (SQLException sqlEx) 
        // log this
      
    
    if (conn != null) 
      try 
        //
        // If we got here, and conn is not null, the
        // transaction should be rolled back, as not
        // all work has been done
        try 
          conn.rollback();
         finally 

          conn.close();
        
       catch (SQLException sqlEx) 
        //
        // If we got an exception here, something
        // pretty serious is going on, so we better
        // pass it up the stack, rather than just
        // logging it. . .
        throw sqlEx;
      
    
  
 while (!transactionCompleted && (retryCount > 0));

【讨论】:

如果您在运行查询时断开连接,您可能会在下次尝试时再次断开连接。如果发生这种情况,请解决真正的问题。

以上是关于带自动重新连接的 JDBC 连接的主要内容,如果未能解决你的问题,请参考以下文章

JDBC 连接超时无法重新连接

JDBC 连接超时无法重新连接

Druid 连接池,重启Mysql数据库后,Druid会自动重新连接不,该在哪配置?

数据库重新启动后尝试重新连接 jdbc 池数据源

Tomcat 在数据库重新启动时未重新连接 PostgreSQL JDBC 池

spring-boot:数据库中断后jdbc重新连接