有没有一种安全的方法来判断 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 1
或 SELECT 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:无法连接、 如何处理这种问题