Должны ли JDBC Resultsets и Statement быть закрыты отдельно, хотя впоследствии было закрыто Соединение? - PullRequest
229 голосов
/ 22 декабря 2010

Говорят, что это хорошая привычка - закрывать все ресурсы JDBC после использования. Но если у меня есть следующий код, нужно ли закрывать Resultset и Statement?

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) {};
}

Вопрос в том, выполняет ли закрытие соединения какую-либо работу или оставляет какие-либо ресурсы в использовании.

Ответы [ 11 ]

181 голосов
/ 22 декабря 2010

То, что вы сделали, является идеальной и очень хорошей практикой.

Причина, по которой я говорю, что это хорошая практика ... Например, если по какой-то причине вы используете «примитивный» тип пула баз данных, и выЗвоните connection.close(), соединение будет возвращено в пул и ResultSet / Statement никогда не будет закрыто, и тогда вы столкнетесь с множеством новых проблем!

Так что вы не всегда можете считатьна connection.close() для очистки.

Надеюсь, это поможет:)

110 голосов
/ 31 марта 2013

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 не может быть создан.

65 голосов
/ 22 декабря 2010

Из Javadocs :

Когда объект Statement закрыт, его текущий ResultSet объект, если он есть существует, также закрыто.

Однако в javadoc не очень ясно, закрыты ли Statement и ResultSet при закрытии базового Connection. Они просто утверждают, что закрытие соединения:

Освобождает этот Connection объект база данных и ресурсы JDBC сразу вместо ожидания они будут автоматически освобождены.

По моему мнению, всегда явно закрывайте ResultSets, Statements и Connections, когда вы закончите с ними, поскольку реализация close может варьироваться между драйверами базы данных.

Вы можете сэкономить много кода, используя такие методы, как closeQuietly в DBUtils от Apache.

35 голосов
/ 22 декабря 2010

Я сейчас использую Oracle с Java. Вот моя точка зрения:

Вы должны явно закрыть ResultSet и Statement, поскольку у Oracle ранее возникали проблемы с сохранением курсоров открытыми даже после закрытия соединения. Если вы не закроете ResultSet (курсор), он выдаст ошибку типа Максимальное количество открытых курсоров превысило .

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

Вот учебник Закрыть ResultSet, когда закончите :

Закрыть ResultSet после завершения

Закрыть ResultSet объект, как только вы закончите работа с ResultSet даже объектом хотя Statement объект закрывает ResultSet объект неявно, когда он закрывает, закрывая ResultSet явно дает возможность сборщику мусора вспомни память как можно раньше потому что ResultSet объект может занимать много памяти в зависимости от запроса.

ResultSet.close();

6 голосов
/ 13 января 2016

Если вам нужен более компактный код, я предлагаю использовать 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);
}
3 голосов
/ 07 апреля 2019

Не имеет значения, является ли Connection пулом или нет. Даже соединение с бассейном должно быть очищено перед возвращением в бассейн.

«Очистить» обычно означает закрытие наборов результатов и откат любых ожидающих транзакций, но не закрытие соединения, в противном случае пул теряет смысл.

3 голосов
/ 11 октября 2012

Правильный и безопасный метод для закрытия ресурсов, связанных с 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();
}
0 голосов
/ 07 апреля 2019

Некоторые удобные функции:

public static void silentCloseResultSets(Statement st) {
    try {
        while (!(!st.getMoreResults() && (st.getUpdateCount() == -1))) {}
    } catch (SQLException ignore) {}
}
public static void silentCloseResultSets(Statement ...statements) {
    for (Statement st: statements) silentCloseResultSets(st);
}
0 голосов
/ 25 марта 2019

Насколько я помню, в текущем JDBC Resultsets и операторы реализуют интерфейс AutoCloseable.Это означает, что они автоматически закрываются после уничтожения или выхода из области видимости.

0 голосов
/ 16 марта 2018

Нет, вам не нужно ничего закрывать, НО соединение. Согласно спецификациям JDBC, закрытие любого более высокого объекта автоматически закроет более низкие объекты. Закрытие Connection закроет все Statement s, которые установило соединение. Закрытие любых Statement закроет все ResultSet с, которые были созданы этим Statement. Не имеет значения, является ли Connection пулом или нет. Даже соединение с бассейном должно быть очищено перед возвращением в бассейн.

Конечно, вы можете иметь длинные вложенные циклы на Connection, создавая множество операторов, а затем их закрытие подходит. Я почти никогда не закрываю ResultSet, хотя при закрытии Statement или Connection кажется чрезмерным, БУДЕТ их закрывать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...