2009-08-27 131 views
0

我不斷收到此異常用DbUnit在同一個地方:DbUnit和SQL Server快速插座關閉

org.dbunit.dataset.DataSetException: com.microsoft.sqlserver.jdbc.SQLServerException: Socket closed 
at org.dbunit.database.DatabaseTableMetaData.getColumns(DatabaseTableMetaData.java:359) 

Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: Socket closed 
at com.microsoft.sqlserver.jdbc.SQLServerConnection.terminate(Unknown Source) 
at com.microsoft.sqlserver.jdbc.TDSChannel.read(Unknown Source) 
at com.microsoft.sqlserver.jdbc.TDSReader.readPacket(Unknown Source) 
at com.microsoft.sqlserver.jdbc.TDSReader.readPacket(Unknown Source) 
at com.microsoft.sqlserver.jdbc.TDSCommand.startResponse(Unknown Source) 
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(Unknown Source) 
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(Unknown Source) 
at com.microsoft.sqlserver.jdbc.TDSCommand.execute(Unknown Source) 
at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(Unknown Source) 
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(Unknown Source) 
at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(Unknown Source) 
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeQueryInternal(Unknown Source) 
at com.microsoft.sqlserver.jdbc.SQLServerDatabaseMetaData.getResultSetFromStoredProc(Unknown Source) 
at com.microsoft.sqlserver.jdbc.SQLServerDatabaseMetaData.getResultSetWithProvidedColumnNames(Unknown Source) 
at com.microsoft.sqlserver.jdbc.SQLServerDatabaseMetaData.getColumns(Unknown Source) 
at org.dbunit.database.DefaultMetadataHandler.getColumns(DefaultMetadataHandler.java:52) 
at org.dbunit.database.DatabaseTableMetaData.getColumns(DatabaseTableMetaData.java:315) 
... 15 more 

試圖讀取來自列元數據時,會出現這種情況表。執行此操作的代碼如下所示:

new DefaultTable(tableName, 
        Columns.getColumns(columns, 
          connection.createDataSet(new String[]{tableName}) 
            .getTableMetaData(tableName).getColumns() 
        ) 
      ) 

連接是MsSqlConnection實例。起初我認爲這是一個網絡問題,但是這個理論有兩個問題。首先運行測試的服務器和數據庫都是同一個xen服務器上的虛擬機,所以沒有真正的網絡。其次,雖然問題不一致,但每次都發生在同一個地方。有超過100個數據庫測試,但同一個失敗(失敗時)。

有沒有人跑過類似的問題?任何見解?

+0

你看,如果你的測試之間有任何耦合... 如果它「隨機失敗」,你可能會改變以前的測試環境。 – 2009-08-27 22:19:30

+0

這是一個很好的建議,但我沒有看到耦合。數據庫連接似乎每次都會創建並關閉。 – Yishai 2009-08-27 22:25:24

+0

我們在虛擬機中運行一些軟件時遇到了奇怪的網絡問題。在一個案例中,我們的源代碼管理系統會隨機丟失連接。我們最終放棄並將其移至自己的專用盒子中。可能不適合你,但我想我會把它扔在那裏。 – 2009-08-27 22:35:46

回答

2

經過一些有意義的演示之後,還有其他代碼測試代碼正在讀取元數據但未關閉結果集。問題現在消失了。

我的理論如下。爲了在MSSQL中獲取數據庫元數據,您必須連接到與當前連接不同的數據庫。一種方法是更改​​數據庫(MSSQL中有一個使用命令)。這種方法的問題在於,你可能會將當前連接的事務搞亂,並且如果多個線程訪問同一個連接,就會引入線程問題。

因此,解決方案可能會在引擎蓋下打開單獨的連接,但共享一個連接對象用於整個連接,如果不是整個虛擬機。 JDBC只公開一個可以關閉的結果集,所以如果你沒有在結果集上調用close並關閉它,他們可能會放置一個關閉連接的終結器。問題在於,如果別的東西在同一時間讀取元數據,它的連接就會從它下面關閉,因此我的崩潰。

鑑於這些測試運行發生在非常一致的代碼路徑上,內存使用模式肯定有可能運行時相當穩定,導致垃圾收集同時發生,但並不總是完全相同時間,這符合它並不總是在完全相同的地方崩潰的觀察。

這就是理論。我不確定如何確認,但除非問題再次出現,這是我的假設。獲得的經驗:總是關閉閱讀元數據的結果集(一般來說)。編輯(很長一段時間後):儘管總體上上述可能仍然如此,但代碼中還存在另一個問題 - 它使用了終結器本身。所以你有一個關於連接的封裝器,它關閉了終結器中的連接,但讓連接暴露給其他人。另一個重要的編碼規則:如果您的終結器關閉資源,請務必確保沒有引用包含它們的類的任何內容都不能訪問這些資源。