Закрытие PreparedStatements - PullRequest
9 голосов
/ 15 июля 2011

Создает ли PreparedStatements и ResultSets «новый экземпляр базы данных» каждый раз, когда они используются? Или, другими словами, если я использую PreparedStatement и ResultSet, я должен закрывать их после каждого использования или после завершения?

Пример:

while (...){
        p = connection.prepareStatement(...);
        r = p.executeQuery();
        while (r.next()) {
        ....
        }
 }
 // We close at the end. Or there are any other p and r still opened...?
 p.close();
 r.close();

OR

while (...){
        p = connection.prepareStatement(...);
        r = p.executeQuery();
        while (r.next()) {
        ....
        }
        p.close();
        r.close();
 }

ПРИМЕЧАНИЕ. Конечно, я бы использовал правильную попытку закрытия, это всего лишь пример.

Ответы [ 3 ]

5 голосов
/ 15 июля 2011

Первый способ лучше.

Однако вы должны знать, что вы можете повторно использовать подготовленные операторы (отсюда и название «подготовленные»), если используемый вами SQL каждый раз один и тот же. Например:

//Note: try/catch/finally blocks removed for brevity
p = connection.prepareStatement(...);
while (...){
    r = p.executeQuery();
    while (r.next()) {
        ....
    }
    r.close();
}
p.close();
5 голосов
/ 15 июля 2011

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

Таким образом, при включении блоков try это будет выглядеть так:

while (...){
        PreparedStatement p = connection.prepareStatement(...);
        try {
          ResultSet r = p.executeQuery();
          try {
            while (r.next()) {
              ....
            }
          } finally {
            try {
              r.close();
            } catch (SQLException e) {
            // log this or something -- prevent these from masking original exception
            }
          }
        }
        finally {
          try {
            p.close();
          } catch (SQLException e) {
            // log this or something -- prevent these from masking original exception
          }
        }
 }

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

Также имейте в виду, что использование try-with-resources будет работать, за исключением того, что если у вас есть случай, когда операция с базой данных завершается успешно, но вызов close приводит к исключению, то исключение будет выдано.

Я рекомендую людям использовать библиотеку spring-jdbc (которая обрабатывает закрытие всего для вас) вместо того, чтобы вручную запускать iffy или verbose jdbc.

1 голос
/ 15 июля 2011

Даже если вы не хотите использовать Spring, Apache DbUtils и т. П., Признайте, что здесь есть МНОГО шаблонного шаблона, который вы хотите исключить из своих подпрограмм обработки, чтобы вам пришлось повторять его несколько раз.насколько возможно.

...