2009-08-27 5 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

Вы посмотрели, существует ли какая-либо связь между вашими испытаниями ... Если это «случайно не удается», вы можете изменить среду в предыдущем тесте. –

+0

Его хорошее предложение, но нет связи, которую я могу сказать. Кажется, что соединение с базой данных было очищено и закрыто каждый раз. – Yishai

+0

У нас были странные проблемы с сетью, запускающие какое-то программное обеспечение на виртуальных машинах. В одном случае наша система управления исходным кодом будет случайным образом потерять соединения.В конце концов мы сдались и перенесли его в свою специальную коробку. Возможно, это не вариант для вас, но я думал, что выброшу его. –

ответ

2

После некоторой значимой игры с этим был другой код кода кода, который читал метаданные, но не закрывал результирующий набор. Теперь проблема исчезла.

Моя теория такова. Чтобы получить метаданные базы данных в MSSQL, вам нужно подключиться к другой базе данных, чем текущее соединение. Один из способов сделать это - изменить базы данных (в MSSQL используется команда use). Проблема с этим подходом заключается в том, что вы можете испортить транзакцию с текущим подключением и будете вводить проблемы с потоками, если более одного потока обращается к одному и тому же соединению.

Таким образом, решение, вероятно, откроет отдельное соединение под капотом, но поделится одним объектом соединения для общего соединения, если не для всей виртуальной машины. JDBC только предоставляет набор результатов, который может быть закрыт, поэтому они могут поставить финализатор, который закрывает соединение, если вы не вызвали закрытие набора результатов и не закрыли его самостоятельно. Проблема в том, что, если что-то еще читает метаданные одновременно, у него есть соединение, закрытое из-под него, поэтому мой сбой.

Учитывая, что эти тестовые прогоны происходили на очень последовательном кодовом пути, конечно, возможно, что шаблон использования памяти был довольно стабильным, чтобы запустить его, вызывать сборку мусора одновременно, но не всегда точно время, которое соответствует наблюдению, что он не всегда терпел крах точно в одном и том же месте.

Это теория. Я не уверен, как подтвердить это, но если проблема не вернется, это мое предположение. Извлеченный урок: всегда закрывайте результирующий набор от чтения метаданных (и вообще).

EDIT (после долгого времени): Хотя в целом выше все еще может быть правдой, в коде возникла еще одна проблема - она ​​использовала сам финализатор. Таким образом, у вас была обертка вокруг соединения, которое закрывало соединение в финализаторе, но позволяло подключиться к другим. Другое важное правило кодирования: если ваш финализатор закрывает ресурсы, всегда убедитесь, что ничто не может получить доступ к этим ресурсам без ссылки на класс, содержащий их.

Смежные вопросы