Должны ли результирующие наборы и операторы JDBC закрываться отдельно, хотя соединение закрывается после этого?
считается хорошей привычкой закрывать все ресурсы JDBC после использования. Но если у меня есть следующий код, необходимо ли закрывать Resultset и оператор?
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = // Retrieve connection
stmt = conn.prepareStatement(// Some SQL);
rs = stmt.executeQuery();
} catch(Exception e) {
// Error Handling
} finally {
try { if (rs != null) rs.close(); } catch (Exception e) {};
try { if (stmt != null) stmt.close(); } catch (Exception e) {};
try { if (conn != null) conn.close(); } catch (Exception e) {};
}
вопрос в том, выполняет ли закрытие соединения эту работу или оставляет некоторые ресурсы в использовании.
8 ответов
что вы сделали идеально и очень хорошая практика.
причина, по которой я говорю свою хорошую практику... Например, если по какой-то причине вы используете "примитивный" тип пула баз данных и вызываете connection.close()
, соединение будет возвращено в пул и ResultSet
/Statement
никогда не будет закрыт, а затем вы столкнетесь со многими новыми проблемами!
так что вы не всегда можете рассчитывать на connection.close()
очистить.
надеюсь, это поможет:)
в Java 1.7 делает нашу жизнь намного проще благодаря оператор try-with-resources.
try (Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement()) {
try (ResultSet resultSet = statement.executeQuery("some query")) {
// Do stuff with the result set.
}
try (ResultSet resultSet = statement.executeQuery("some query")) {
// Do more stuff with the second result set.
}
}
этот синтаксис довольно краткий и элегантный. И connection
действительно будет закрыт, даже если statement
не удалось создать.
теперь я использую Oracle с Java. Вот моя точка зрения:--11-->
вы должны закрыть ResultSet
и Statement
явно, потому что Oracle имеет проблемы с сохранением курсоров открытыми даже после закрытия соединения. Если вы не закроете ResultSet
(курсор) он выдаст ошибку, как максимальное число открытых курсоров превысило.
Я думаю, что вы можете столкнуться с той же проблемой с другими базами данных, которые вы используете.
вот учебник закрыть ResultSet по завершении:
закрыть ResultSet по завершении
закрыть
ResultSet
объект, как только вы закончите работа сResultSet
объект даже хотя
Если вы хотите получить более компактный код, я предлагаю использовать Apache Commons DbUtils. В этом случае:
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = // Retrieve connection
stmt = conn.prepareStatement(// Some SQL);
rs = stmt.executeQuery();
} catch(Exception e) {
// Error Handling
} finally {
DbUtils.closeQuietly(rs);
DbUtils.closeQuietly(stmt);
DbUtils.closeQuietly(conn);
}
правильный и безопасный метод для закрытия ресурсов, связанных с JDBC this (взято из Как правильно закрыть ресурсы JDBC-каждый раз):
Connection connection = dataSource.getConnection();
try {
Statement statement = connection.createStatement();
try {
ResultSet resultSet = statement.executeQuery("some query");
try {
// Do stuff with the result set.
} finally {
resultSet.close();
}
} finally {
statement.close();
}
} finally {
connection.close();
}
с формой Java 6 я думаю, что лучше проверить, что она закрыта или нет до закрытия (например, если какой - то пул соединений выселяет соединение в другом потоке) - например, какая-то сетевая проблема-оператор и состояние resultset могут быть закрыты. (это не часто случается, но у меня была эта проблема с Oracle и DBCP). Мой шаблон для этого (в более старом синтаксисе Java):
try {
...
return resp;
} finally {
if (rs != null && !rs.isClosed()) {
try {
rs.close();
} catch (Exception e2) {
log.warn("Cannot close resultset: " + e2.getMessage());
}
}
if (stmt != null && !stmt.isClosed()) {
try {
stmt.close();
} catch (Exception e2) {
log.warn("Cannot close statement " + e2.getMessage());
}
}
if (con != null && !conn.isClosed()) {
try {
con.close();
} catch (Exception e2) {
log.warn("Cannot close connection: " + e2.getMessage());
}
}
теоретически это не 100% идеально, потому что между проверкой состояния закрытия и закройте себя есть немного места для изменения состояния. В худшем случае вы получите предупреждение в лонг. - но это меньше, чем возможность изменения состояния в долгосрочных запросах. Мы используем этот шаблон в производстве с загрузкой "avarage" (150 одновременных пользователей), и у нас не было проблем с ним - поэтому никогда не видите это предупреждающее сообщение.
нет, вам не нужно ничего закрывать, кроме соединения. В спецификации JDBC для закрытия выше объект автоматически закрылись выше объекты. Закрытие Connection
закрытие Statement
s, которое создало соединение. Закрытие любого Statement
закрыть все ResultSet
s, которые были созданы этим Statement
. Не имеет значения, если Connection
является объединяемым или нет. Даже poolable соединение должно очистить перед возвращением в бассейн.
конечно, у вас могут быть длинные вложенные циклы на Connection
создание множества операторов, а затем их закрытие подходит. Я почти никогда не закрыть!--3--> хотя, кажется чрезмерным при закрытии Statement
или Connection
закроет их.