Java 通过JDBC“ping”数据库的最佳方式是什么?

Java 通过JDBC“ping”数据库的最佳方式是什么?,java,jdbc,Java,Jdbc,我试图确定通过JDBC ping数据库的最佳方法。我所说的“最佳”是指快速和低开销。例如,我考虑执行以下操作: "SELECT 1 FROM DUAL" 但是我相信双表是Oracle特有的,我需要一些更通用的东西 请注意,连接有一个isClosed方法,但javadoc声明这不能用于测试连接的有效性。是的,这只适用于Oracle,但在JDBC中没有通用的方法 大多数连接池实现都有一个配置参数,您可以在其中指定将用于ping的SQL,从而推动责任,以确定如何对用户执行ping 这似乎是最好的方法

我试图确定通过JDBC ping数据库的最佳方法。我所说的“最佳”是指快速和低开销。例如,我考虑执行以下操作:

"SELECT 1 FROM DUAL"
但是我相信双表是Oracle特有的,我需要一些更通用的东西


请注意,连接有一个isClosed方法,但javadoc声明这不能用于测试连接的有效性。

是的,这只适用于Oracle,但在JDBC中没有通用的方法

大多数连接池实现都有一个配置参数,您可以在其中指定将用于ping的SQL,从而推动责任,以确定如何对用户执行ping


这似乎是最好的方法,除非有人为此提供了一个小小的帮助工具。当然,它排除了使用可能更快的非基于SQL的方法,例如

我可能会在这一个上吃午饭,但您是否可以简单地执行一些无意义的查询,例如:

SELECT * FROM donkey_giraffe_87

我对JDBC的错误处理不太了解,但是您可以检查一下数据库是否至少告诉您表不存在。如果JDBC的错误代码是特定于供应商的,那么Spring框架有一些实用程序可以将这些代码映射到更有意义的异常。对于IBM在iSeries和其他DB2系统上的UDB来说,可能是这样

select 1 from SYSIBM.SYSDUMMY1;

只要发出以下查询就足够了

SELECT 1

您可以尝试从连接元数据中获取db名称,并执行匹配的sql语句。例如

Connection con = null;
Statement st = null;
ResultSet rs = null;
try {
  con = dataSource.getConnection();
  String dbProductName = con.getMetaData().getDatabaseProductName();
  Statement st = con.createStatement();
  if ( "PostgreSQL".equalsIgnoreCase(dbProductName) ) {
    rs = st.executeQuery("select version();");
  } else if ( "Oracle".equalsIgnoreCase(dbProductName) ) {
    rs = st.executeQuery("select 1 from dual");
  } else {
   ...
  }
} catch ( Exception ex ) {
  System.out.prinln("DB not reachable");
} finally {
   // close statement, connection etc.
   ...
}
使用JDBC4,您可以从连接接口使用isValidint。这基本上就是你的审判陈述

有些驱动程序通过向数据库发送正确的伪SQL来实现这一点,有些驱动程序直接使用低级操作来减少解析开销


但是,要注意超时,有些驱动程序DB/400和Oracle精简版确实会为每次调用生成一个新的时间线程,这对于大多数池验证场景来说是不可接受的。Oracle似乎也没有使用预先准备好的语句,所以它有点依赖于隐式缓存。

MySQL有一个很好的机制,本文对此进行了说明。答案如下:

这实际上会导致驱动程序向服务器发送一个ping,并返回一个伪造的、轻量级的结果集


话虽如此,使用JDBC 4的Connection.isValidint是最好的选择。

尝试查询不存在的表可能会很昂贵。字典缓存未命中和错误处理代码。ORA-00923:FROM关键字未找到expectedThis is postgres specific我在MS SQL Server上使用了SELECT@@VERSION,但这甚至不是SQL。在MSSQL上,Microsoft JDBC驱动程序使用SELECT 1进行验证。请看我的答案,JDBC 4有一个通用的原因,但并非所有驱动程序都提供JDBC 4。AS400JDBCConnection.isValid对于jtopen的java8/jdbc40版本是有效的,通过使用内部函数和无需解析的SQL字符串,因此只要不指定超时,就会产生一个计时器线程,效率就会更高
"/* ping */ SELECT 1"