Закрытие соединений базы данных в 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 или соединение из пула.