Intereting Posts
Почему JPanel не отображается правильно, когда я устанавливаю свою программу в полноэкранный режим? Почему Arrays.sort – алгоритм быстрой сортировки, почему бы и не использовать другой алгоритм сортировки? Единичные тесты против интеграционных тестов с весной Загрузка большого текста в Android Метод должен возвращать тип int Как найти объект данного типа в гетерогенном списке Мой CipherOutputStream терпит неудачу Эффективность Clojure для дорогостоящих алгоритмов Jackson ObjectMapper не может десериализовать POJO, выдает исключение: не найдено подходящего конструктора для типа : невозможно создать экземпляр из объекта JSON Как получить количество дней в течение данного месяца с помощью Joda-Time? Log4j: один файл журнала за запрос Соединение SFTP через Java, запрашивающее странную аутентификацию Тег в web.xml не вызывает java.lang.Throwable Exceptions Eclipse 3.5 Невозможно установить плагины Android GET и POST Request

Каков подходящий способ закрыть соединение с базой данных в Java?

Я попытался закрыть соединение с БД. Но у него была путаница, скажем,

ResultSet rs = null 

Имею ли я это рядом с

 rs.close(); 

Или

 DatabaseUtil.closeResultSet(rs); 

В чем разница между ними?

Эти методы закрывают только ResultSet . Вам все равно придется закрыть все экземпляры Statement и Connection . Я рекомендую сделать это в блоке finally . Что-то вроде,

 Connection conn = null; Statement stmt = null' ResultSet rs = null; try { conn = getConnection(); stmt = conn.prepareStatement(sql); stmt.setString(1, "Hello"); rs = stmt.executeQuery(); while (rs.next()) { // ... } } catch (SQLException se) { se.printStackTrace(); } finally { if (rs != null) { try { rs.close(); } catch (Exception e) { e.printStackTrace(); } } if (stmt != null) { try { stmt.close(); } catch (Exception e) { e.printStackTrace(); } } if (conn != null) { try { conn.close(); } catch (Exception e) { e.printStackTrace(); } } } 

Если вы используете мою утилиту Close блок finally может быть,

 } finally { Close.close(rs, stmt, conn); } 

Закрытие resultSet не закрывает соединение с базой данных. Вам нужно сделать это отдельно.

Обычно вы хотите закрыть ресурс следующим образом:

 if (resultSet != null) { try { resultSet.close(); } catch (SQLException e) { log.info("closing resultset caused exception", e); } } 

Если это то, что делает ваш DatabaseUtil, тогда это было бы предпочтительнее.

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

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

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

 Class Class1 { public T getColumn(DataSource ds) { T value = null; Connection con = null; Statement st = null; try { con = ds.getConnection(); st = con.createStatement(); ResultSet rs = st.executeQuery("select 1 from dual"); rs.next(); Object o = rs.getObject(1); // I want an Integer but a BigDecimal is created! value = (T) o; // ClassCastException here! } finally { if (st != null) { st.close(); } if (con != null) { con.close(); } } return i; } } 

Если statement.close выбрасывает SQLException, тогда следующая строка в блоке finally никогда не будет вызвана, соединение не будет закрыто, и соединение с базой данных будет зависать до неиспользования до истечения времени ожидания. Это может показаться неудачным, поскольку это только одно соединение, но любое другое соединение может видеть одно и то же поведение, и при правильных обстоятельствах вы можете привести все это приложение таким образом (выбрасывая все соединения с базой данных). См . Книгу Майкла Найгарда « Отпустите это! для истории, описывающей очень дорогое и болезненное отключение приложений для предприятий, которое было прослежено до кода именно так.

Необходимость вырезать и вставлять этот код закрытия ресурса является уродливым, было бы лучше внедрить что-то вроде метода шаблона, который передается в mapper для набора результатов, так что закрытие выполняется только в одном месте. Но это ставит вас на путь переосмысления spring-jdbc , который уже сделал все это для вас.

Jdbc api сообщает нам, что закрытие соединения закроет результирующие наборы и инструкции. Заявления закрытия закрывают результирующий набор. Но я всегда закрываю каждый набор результатов и каждое утверждение сам, потому что я столкнулся с проблемами, которые не делают этого. Просто используйте метод close, предоставленный вами результирующим набором, инструкцией и соединением.

Я думаю, что лучший способ – сделать все в рамках try-with-resources

 try(conn=openConnection()){ try(rs=conn.getResultSet()){ } } 

Чтобы вы были полностью уверены, что ресурсы будут закрыты в конце.

Оба способа работают, но я предпочитаю первый rs.close (); , без подписи, чтобы проверить, не является ли rs недействительным, и заключить ваш вызов с помощью инструкции try..catch, поэтому вам нужно закрыть ваше соединение в финальном блоке, даже если Java7 закрывает все для вас.

проверить Java / JDBC: лучший шаблон проектирования для закрытия соединения с базой данных при возникновении исключения

Нормальный код будет выглядеть так:

 Connection connection = null; PreparedStatement stmt = null; ResultSet rs = null; ResultSet rs2 = null; try { connection = getConnection(); stmt = connection.prepareStatement("..."); stmt.setString(":foobar", "Foobar"); rs = stmt.execute ... ; // I don't remember the method return ResultSet while (rs.next()) { ... } stmt.setString(":foobar", "Barfoo"); rs2 = stmt.execute ... ; } finally { if (null != rs2) try {rs2.close();} catch (Exception e) if (null != rs) try {rs.close();} catch (Exception e) {...} if (null != stmt) try {stmt.close();} catch (Exception e) {...} if (null != connection) try {connection.close();} catch (Exception e) {...} } 

Или, в Java 7, используя try-with-resources (предыдущий код почти такой же):

 try (Connection connection = getConnection(); PreparedStatement stmt = connection.prepareStatement("...")) { stmt.setString(":foobar", "Foobar"); try (ResultSet rs = stmt.executeQuery()) { while (rs.next()) { ... } } stmt.setString(":foobar", "Barfoo"); try (ResultSet rs2 = stmt.executeQuery()) { while (rs2.next()) { ... } } } 

Разница проста:

  • вы закрываете ResultSet – чтобы освободить связанный ресурс. В этом примере я использовал PreparedStatement : у вас могут быть параметры, а значит и разные ResultSet . Поскольку это требует памяти и ресурсов, вам нужно закрыть их после того, как вы закончите с ними, иначе сборщик мусора сделает это, и он сделает это только для восстановления памяти.
  • вы закрываете PreparedStatement или Statement когда вам это больше не нужно. Закрытие оператора закрывает связанный ResultSet .
  • вы закрываете Connection когда оно вам больше не понадобится. Закрытие соединения завершает Statement s (и их ResultSet ).

В зависимости от вашей потребности (например, пакетной или веб-сервер), возможно, вам не придется закрывать соединение, когда будет работать Java, но лучше освобождать ресурсы, когда они вам больше не нужны (будь то ресурсы JDBC или файловые ресурсы …).

Закрытие resultSet не закрывает соединение с базой данных. Мы должны закрыть соединение, как показано ниже. Перед закрытием соединения вы должны закрыть другой экземпляр, например, ResultSet, PreparedStatement и Statement.

например

  Connection con = DBUtils.getConnection(); .... PreparedStatemet pstmt = con.getPreparedStatement(); ResultSet rs = pstmt.execute(); while(rs.next()) { } в  Connection con = DBUtils.getConnection(); .... PreparedStatemet pstmt = con.getPreparedStatement(); ResultSet rs = pstmt.execute(); while(rs.next()) { } 

// После того, как вы сделали ResultSet … Пришло время закрыть / выпустить экземпляры.

  if (resultSet != null) { try { resultSet.close(); resultSet = null; } catch (SQLException e) { // ignore the exceptions. } } // Close the Prepared Statement if(theStatement != null) { try { theStatement.close(); theStatement = null; } catch(Exception ignored) { } // Close the Connection if(theConnection != null) { try { theConnection.close(); theConnection = null; } catch(Exception ignored) { }