Закрытие соединений базы данных в Java
Я немного запутался, я читал ниже: http://en.wikipedia.org/wiki/Java_Database_Connectivity
Connection conn = DriverManager.getConnection(
"jdbc:somejdbcvendor:other data needed by some jdbc vendor",
"myLogin",
"myPassword" );
Statement stmt = conn.createStatement();
try {
stmt.executeUpdate( "INSERT INTO MyTable( name ) VALUES ( 'my name' ) " );
} finally {
//It important to close the statement when you are done with it
stmt.close();
}
Вам не нужно закрывать соединение Connect?
Что действительно происходит, если conn.close() не встречается?
У меня есть частное веб-приложение, которое я поддерживаю, которое в настоящее время не закрывает ни одну из форм, но важно ли это, что это действительно одна строка, одна или одна?
Сайт продолжает прерываться, но сервер продолжает говорить о проблеме с подключением к базе данных, мое подозрение в том, что оно не закрывается, но я не знаю, что, если оно закрывается.
Ответы
Ответ 1
Когда вы закончите использовать Connection
, вам нужно явно закрыть его, вызвав его метод close()
, чтобы освободить любые другие ресурсы базы данных (курсоры, дескрипторы и т.д.), к которым может подключиться соединение.
На самом деле безопасный шаблон в Java должен закрыть ваши ResultSet
, Statement
и Connection
(в этом порядке) в блоке finally
, когда вы закончите с ними, что-то вроде этого:
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
// Do stuff
...
} catch (SQLException ex) {
// Exception handling stuff
...
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) { /* ignored */}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException e) { /* ignored */}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) { /* ignored */}
}
}
Блок finally
может быть немного улучшен (чтобы избежать нулевой проверки):
} finally {
try { rs.close(); } catch (Exception e) { /* ignored */ }
try { ps.close(); } catch (Exception e) { /* ignored */ }
try { conn.close(); } catch (Exception e) { /* ignored */ }
}
Но, тем не менее, это очень многословно, поэтому вы обычно используете вспомогательный класс для закрытия объектов в методах вспомогательного метода с нулевым использованием, а блок finally
становится примерно таким:
} finally {
DbUtils.closeQuietly(rs);
DbUtils.closeQuietly(ps);
DbUtils.closeQuietly(conn);
}
И, фактически, Apache Commons DbUtils имеет DbUtils
, который точно делает это, поэтому нет необходимости писать свои собственные.
Ответ 2
Всегда лучше закрыть объекты базы данных/ресурсов после использования.
Лучше закрыть соединения, объекты результатов и утверждения в блоке finally
.
До Java7 все эти ресурсы необходимо закрыть с помощью блока finally
.
Если вы используете Java 7, то для закрытия ресурсов вы можете сделать следующее.
try(Connection con = getConnection(url, username, password, "org.postgresql.Driver");
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(sql);
) {
//statements
}catch(....){}
Теперь объекты con, stmt и rs становятся частью блока try, а java автоматически закрывает эти ресурсы после использования.
Надеюсь, что я был полезен.
Ответ 3
Да. Вам нужно закрыть результаты, инструкцию и соединение. Если соединение произошло из пула, его закрытие фактически отправляет его обратно в пул для повторного использования.
Обычно вам нужно сделать это в блоке finally{}
, так что если генерируется исключение, вы все равно получите возможность закрыть это.
Многие фреймворки будут следить за этой проблемой выделения/освобождения ресурсов для вас. например Spring JdbcTemplate. У Apache DbUtils есть методы, чтобы следить за закрытием набора результатов/утверждения/соединения, будь то null или нет (и catching exceptions при закрытии), что также может помочь.
Ответ 4
Достаточно закрыть только Statement
и Connection
. Нет необходимости явно закрывать объект ResultSet
.
Документация Java говорит о java.sql.ResultSet
:
Объект ResultSet автоматически закрывается объектом Statement, который сгенерировал его, когда этот объект Statement закрыт, повторно выполняется или используется для извлечения следующего результата из последовательности нескольких результатов.
Спасибо BalusC за комментарии: "Я бы не стал полагаться на это. Некоторые драйверы JDBC терпят неудачу."
Ответ 5
Да, вам нужно закрыть Connection. В противном случае клиент базы данных обычно будет поддерживать соединение сокета и другие ресурсы.
Ответ 6
На самом деле, лучше всего использовать блок try-with-resources, и Java закроет все подключения для вас, когда вы выйдете из блока try.
Вы должны сделать это с любым объектом, который реализует AutoClosable.
try (Connection connection = getDatabaseConnection(); Statement statement = connection.createStatement()) {
String sqlToExecute = "SELECT * FROM persons";
try (ResultSet resultSet = statement.execute(sqlToExecute)) {
if (resultSet.next()) {
System.out.println(resultSet.getString("name");
}
}
} catch (SQLException e) {
System.out.println("Failed to select persons.");
}
Вызывается вызов getDatabaseConnection. Замените его вызовом, который получает соединение JDBC SQL или соединение из пула.