2013-06-19 79 views
1

我有一個查詢數據庫和結果通過java.sql.ResultSet獲得,因爲這個查詢是動態的,列數返回可能是5或7,在過去與相同它的代碼生成一個「列未發現異常」,並載於以下陷阱:ResultSet「未找到列」與c3p0

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

但現在用相同的try和catch(唯一的區別是,現在我使用combopooldatasource及其連接) ,我得到了兩個不屬於捕獲的例外。

我該如何改進這一點,有沒有更好的方法來檢查列是否存在? c3p0是否必須強制測試基於(SQLState: S0022) column not found error的連接?

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

回答

0

檢查ResultSetMetaData

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一起使用;只需要catch Throwable(它確實讓我不寒而慄,雖然:)

try { 
    sTemp = this.rsResults.getString("col3"); 
} catch (Throwable t) { 
    // Both, Exceptions and Errors are ignored now 
} 
+0

感謝您的迴應,ResultSetMetaData如果罰款檢查col3是否存在,但col3更改它在select語句中的位置。ResultSet的getString方法非常完美,因爲如果列不存在,將返回異常,如http://docs.oracle.com/javase/6/docs/api/java/sql/ResultSet.html#getString(java .lang.String),我的問題是在使用c3p0時出現這種特殊的異常。 – AndreFonseca

+0

@AndreFonseca請檢查我的更新。 –

+0

我不喜歡Throwable,因爲我不想記錄任何東西,並且不得不處理任何可能出現的錯誤和異常,除了未找到的列以外。我會修改源代碼,這是最好的方法。 – AndreFonseca

1

C3P0內部測試上的任何類型的異常連接,但這次試驗沒有拋出異常或可見的客戶端代碼。您只能看到它,因爲您正在以DEBUG級別記錄c3p0輸出。 c3p0的東西應該在INFO上記錄下來以便正常使用。如果您登錄DEBUG-ish級別,則會看到各種警報消息和堆棧跟蹤。

+0

是的,這是真的,但如果我將日誌記錄設置爲INFO,連接測試仍會發生?如果是的話,提高測試成本加上堆棧的異常仍然會很高,這就是我想要避免 – AndreFonseca

+0

是的,測試仍然會發生。 c3p0假設異常表示異常情況,並且在異常之後總是測試以確定連接是否適合在池中重用,或者應在關閉時標記爲銷燬。如果設置preferredTestQuery或automaticTestTable屬性,則連接測試不需要非常昂貴。但是,默認測試通常很慢。 –

+0

好的,謝謝你史蒂夫。我認爲Exception(col未找到)的代價是最讓我困擾的,我使用原始代碼進行了一些測試(使用SQLException列未找到的try&catch)以及修改後的代碼(檢查列是否存在於ResultSet.getString之前())所有有和沒有c3p0,我會在這裏發佈結果時完成。 – AndreFonseca

0

我做了以下(粗略)測試只是爲了說明引發異常與檢查RecordSet中是否存在列的代價,在我的具體情況中。

的列數,以檢查是169.

代碼1

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){} 

代碼2與功能hasColumn [問題]:How can I determine if the column name exist in the ResultSet?

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

  code 1 code 2 
query nº1 75ms  36ms 
query nº2 40ms  43ms 
query nº3 227ms 46ms 
query nº4 262ms 18ms 

個結果與C3P0日誌級別在INFO

  code 1 code 2 
query nº1 519ms  45ms 
query nº2 358ms  28ms 
query nº3 2348ms 9ms 
query nº4 3243ms 12ms 

作爲結論引發異常的成本只是爲了檢查是否存在的列(除了的是不好的做法)是在這兩種情況下,尤其是如果使用C3P0高。