有没有一种安全的方法来判断 JDBC 连接是不是仍然正常?

Posted

技术标签:

【中文标题】有没有一种安全的方法来判断 JDBC 连接是不是仍然正常?【英文标题】:Is there a safe way to tell if a JDBC connection is still ok?有没有一种安全的方法来判断 JDBC 连接是否仍然正常? 【发布时间】:2012-12-28 12:26:26 【问题描述】:

我们有一个网络服务器处理来自客户的请求。此 Web 服务器的一个组件拥有与数据库的连接。

在开始使用连接之前,我需要能够识别连接是否已关闭或以某种方式不再起作用。目前我在做类似的事情:

// Decide connection details on alias.
private String alias = null;
// I must have my own because I prepare statements.
private Connection connection = null;

public Connection getConnection() 
  try 
    if ( connection.isClosed() ) 
      // Start afresh.
      connection = null;
    
    // ** More tests here to check connection is ok.
    if (connection == null) 
      // Make a new connection.
      connection = Connections.getConnection(alias);
    
   catch (SQLException ex) 
    // Cause a NPE further down the line.
    connection = null;
  
  return connection;

遗憾的是,这有时会返回如此陈旧的连接,以至于我得到了各种错误之一。一个这样的样子:

java.sql.SQLException:Io 异常:软件导致连接中止:套接字写入错误

请注意,这只是记录的错误之一,此错误发生在大约 72 小时空闲后。

我正在寻找的是一个最小的数据库通用连接测试器,它应该始终如一地判断连接是否启动、运行和稳定。这可能吗?

我不介意对它运行一个非常小的查询,但它必须与数据库无关,并且几乎不需要时间/资源。

顺便说一句:我在 Java 5 下运行,所以 Connection.isValid 不是我的解决方案。


已添加

对于那些稍后访问此问题的人 - 我最终接受了提供的建议并转移到了一个真正的连接池,这不仅非常容易做到,而且 所有 我的问题都消失了。 p>

唯一奇怪的部分是意识到使用连接池时,您必须在完成连接后close 连接 - 池拦截关闭并将其返回到幕后的池中。

【问题讨论】:

您对现成的连接池有什么看法,因为它们会定期验证连接? @MarkoTopolnik - 什么都没有 - 因此我已经准备好附加到这些连接的声明,所以我必须自己处理它们。还是我? 实际上,这些池也处理准备好的语句池的问题。顺便说一句,我的选择是 boneCP 是的,一个像样的游泳池应该为您处理这个问题。您的代码向我建议您决定独自完成并为自己做。 【参考方案1】:

最好的方法是为 Oracle 执行一个简单的 SQL 语句,例如 SELECT 1SELECT 1 FROM DUAL。 (有关特定于供应商的语法,请查看您的数据库。)

如果失败,请刷新连接。这就是像 WebLogic 这样的 Java EE 应用服务器所做的测试,如果您将它们配置为这样做的话。

【讨论】:

我认为,如果您强调某些应用程序服务器已经自动执行此检查(如果您将它们配置为这样做)这一事实(这在您的答案中似乎有点暗示),那将是可取的。 WebSphere 就是一个很好的例子。 @OldCurmudgeon 它不适用于 Informix、Oracle 或 DB2。刚试了一下。 :) @Jeff - 我肯定需要一个 Oracle 版本或一个也可以与 Oracle 一起使用的版本。 SELECT 1 FROM DUAL 对 Oracle 来说似乎是一个不错的建议,但我更喜欢一个包罗万象的建议。 @OldCurmudgeon:没有。 Oracle 和 DB2 需要特殊的 hack,其他人都使用 SELECT 1 您多久更换一次数据库供应商?我猜很少有。如果你真的很担心,就让它成为一个配置项。【参考方案2】:

试试

java.sql.Connection.isValid(int timeout) 

如果连接尚未关闭并且仍然有效,则返回 true。

【讨论】:

对不起 - 我应该坚持我在 Java 5 下运行。 只是补充一点信息,据我所知,java.sql.Connection.isValid(int timeout) 方法调用SELECT 1【参考方案3】:

每个数据库都有一个不依赖于现有表的查询。对于 Oracle,请尝试

select 1 from dual

对于许多其他数据库(mysql、H2),请尝试

select 1

DB2 有它自己独特的语法:

values 1

【讨论】:

DB2 使用此语法从值列表创建临时表。在文档中搜索VALUES statement【参考方案4】:

就我而言,我使用 java.sql.Connection.isValid(int timeout) :

我有一个 getConnection 方法(或者在这个例子中没有轮询 getInstance):

try 
    if (connect == null) || ! connect.isValid() ) 
        connect.DriverManager.getConnection(...);
 catch (SQLException e) 
    logger.error(...);
    connect = null;

return connect;

【讨论】:

当然值得将此解决方案作为一个选项,但请记住 isValid 仅在 Java 1.6 及更高版本中可用。总的来说 - 我的建议是使用连接池

以上是关于有没有一种安全的方法来判断 JDBC 连接是不是仍然正常?的主要内容,如果未能解决你的问题,请参考以下文章

org.springframework.jdbc.BadSqlGrammarException 错误 求大神帮指导 本人新手

无法在 Spring Boot 中使用 JDBC 身份验证创建安全连接

网页显示无法打开JDBC连接事务;嵌套异常java.sql.SQLException:无法连接、 如何处理这种问题

如何判断是不是连接到网站[关闭]

Laravel SPA 是不是仍应使用 CSRF 令牌来保证安全?

我如何判断我是不是仍在监听 Android 中的套接字