2009-08-27 8 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インスタンスです。最初はネットワーク問題だと思っていましたが、その理論には2つの問題があります。まず、テストを実行しているサーバーとデータベースは、同じxenサーバー上の両方の仮想マシンであるため、実際のネットワークは存在しません。第二に、問題は矛盾していますが、毎回同じ場所で発生します。 100を超えるデータベーステストがありますが、この同じテストは失敗します(失敗した場合)。

は誰もが同じような問題全体を実行していますか?どんな洞察?

+0

それは「ランダムに失敗した」場合は、前のテスト環境を変更することがあります ...あなたのテストの間の任意の結合がある場合は、あなたが見てもらいます。 –

+0

それは良い提案ですが、私が理解できるカップリングはありません。データベース接続は毎回きれいに作成されているようです。 – Yishai

+0

仮想マシンでいくつかのソフトウェアを実行する際に奇妙なネットワーク問題が発生しました。 1つのケースでは、ソース管理システムが無作為に接続を失います。私たちは結局それをあきらめて、それを専用のボックスに移しました。あなたのための選択肢ではないかもしれませんが、私はそこに投げ捨てると思っていました。 –

答えて

2

これでいくつかの重要な演奏した後、メタデータを読み込みますが、結果セットを閉じていなかった他のコードのテストコードがありました。問題は今や消え去った。

私の理論は次のとおりです。 MSSQLでデータベースのメタデータを取得するには、現在の接続とは異なるデータベースに接続する必要があります。これを行う1つの方法は、データベースを変更することです(MSSQLにuseコマンドがあります)。そのアプローチの問題は、現在の接続でトランザクションを混乱させる可能性があり、複数のスレッドが同じ接続にアクセスする場合にスレッドの問題が発生することです。

ので、解決策は、ボンネットの下に別個の接続をオープンする可能性が高いでしたが、全体ではなく、VMの場合、全体的な接続のために1つの接続オブジェクトを共有します。 JDBCは結果セットを閉じることができます。結果セットをクローズしていない場合は、クローズしたファイナライザを置いて自分でクローズすることができます。その問題は、他の何かが同時にメタデータを読んでいる場合、そのメタデータがその下から閉じた状態になり、クラッシュするということです。

非常に一貫したコードパスで起こっていたテストでは、メモリ使用パターンがかなり安定して実行され、ガベージコレクションが同時に発生する可能性がありますが、必ずしも同じではありません時間は、常に同じ場所で必ずしも衝突しないという観察に合っています。

それは理論です。私はそれを確認する方法がわかりませんが、問題が戻ってこない限り、それは私の前提です。教訓:結果セットを常にメタデータの読み込みから閉じることができます(一般的に)。

EDIT(久しぶり):一般的には上記まだ本当かもしれないが、コードで起こっている別の問題があった - それはファイナライザ自体を使用していました。つまり、ファイナライザで接続を閉じていたが、接続を他のものにさらすようにしていた接続の周りにラッパーがありました。もう一つの重要なコーディング規則:ファイナライザーがリソースを閉じると、それらを含むクラスへの参照を持たずにこれらのリソースにアクセスすることができないことが常に確認されます。

関連する問題