关于java:ResultSet与c3p0“找不到列”

ResultSet “column not found” with c3p0

我对数据库进行了查询,结果是通过java.sql.ResultSet获得的,因为此查询是动态的,所以返回的列数可能是5或7,在过去使用相同的代码生成了"找不到列" 例外",并包含在以下捕获中:

1
2
3
try{
    sTemp = this.rsResults.getString("col3");
   }catch(Exception e){}

但是,现在使用相同的try-catch(唯一的区别是,现在我使用的是combopooldatasource及其连接),我得到了两个不属于catch的异常。

我该如何改善,是否有更好的方法检查列是否存在?
c3p0是否必须基于(SQLState: S0022) column not found error强制测试连接?

1
2
3
4
5
Error n1 - in the com.mchange.v2.c3p0.impl.NewProxyResultSet.getString qlUtils.toSQLException() - Attempted to convert SQLException to SQLException. Leaving it alone. [SQLState: S0022; errorCode: 0]
java.sql.SQLException: Column 'col3' not found.

Error n2 -  DefaultConnectionTester.statusOnException() - Testing a Connection in response to an Exception:
java.sql.SQLException: Column 'col3' not found.

ps:使用的驱动程序是相同的org.gjt.mm.mysql.Driver


c3p0在内部对任何异常类型的连接进行测试,但是此测试的异常不会抛出或对客户端代码不可见。您只看到它是因为您正在以DEBUG级别记录c3p0输出。正常使用时,c3p0的内容应记录在INFO中。如果您以DEBUG-ish级别登录,则会看到各种警报消息和堆栈跟踪。


我已经进行了以下(粗略)测试,以说明在我的特殊情况下引发异常与检查RecordSet中是否存在列的开销。

要检查的列数为169。

代码1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
try
{
 sTemp = this.rsResults.getString("col3");
}catch(Exception e){}
try
{
 sTemp = this.rsResults.getString("col4");
}catch(Exception e){}

...

try
{
 sTemp = this.rsResults.getString("col169");
}catch(Exception e){}

带有函数hasColumn的代码2 [问题]:如何确定ResultSet中是否存在列名?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ResultSetMetaData rsmd = null;
try {
     rsmd = this.rsResults.getMetaData();
} catch (SQLException e1) {
 e1.printStackTrace();
}

try{
 if (rsmd != null && hasColumn(rsmd,"col3"))
  sTemp = this.rsResults.getString("col3");
}catch(Exception e){}

try{
 if (rsmd != null && hasColumn(rsmd,"col4"))
  sTemp = this.rsResults.getString("col4");
}catch(Exception e){}

...

try{
 if (rsmd != null && hasColumn(rsmd,"col169"))
  sTemp = this.rsResults.getString("col169");
}catch(Exception e){}

没有c3p0的结果

1
2
3
4
5
           code 1   code 2
query no1   75ms     36ms
query no2   40ms     43ms
query no3   227ms    46ms
query no4   262ms    18ms

INFO的c3p0 loglevel结果

1
2
3
4
5
           code 1   code 2
query no1   519ms     45ms
query no2   358ms     28ms
query no3   2348ms    9ms
query no4   3243ms    12ms

得出的结论是,在两种情况下,尤其是使用c3p0时,仅检查列是否存在而引发异常的成本很高。


检查ResultSetMetaData

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ResultSet rs = stmt.executeQuery("SELECT * FROM your_table");

ResultSetMetaData rsmd = rs.getMetaData();
int numberOfColumns = rsmd.getColumnCount();

// test the number of columns returned
if (numberOfColumns == 5) {
    //
} else {
    // numberOfColumns = 7
}

// or, test the column names
if ("col3".equals(rsmd.getColumnName(3)) {
    // col3 exists
}

编辑:
如果您不想对源代码进行修改,而只希望您当前的方法也可以与c3p0一起使用;赶上Throwable。 (虽然这确实让我发抖:)

1
2
3
4
5
try {
    sTemp = this.rsResults.getString("col3");
} catch (Throwable t) {
    // Both, Exceptions and Errors are ignored now
}