Закрытие соединения с базой данных в Java

#java #sql #jdbc #connection

#java #sql #jdbc #подключение

Вопрос:

У меня есть следующий метод в моем классе базы данных, который возвращает результирующий набор для данного оператора SQL:

 public static ResultSet sqlStatement(String query) throws SQLException{
    ResultSet result = null; 
    Connection conn = connect();
    Statement newStatement = conn.createStatement(); 
    result = newStatement.executeQuery(query);
    conn.close();
    return resu<
}
  

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

 java.sql.SQLException: out of memory
  

Я новичок в Java и экспериментирую, поэтому любая помощь очень ценится.

Комментарии:

1. Увеличьте объем памяти с помощью параметра запуска -Xmx или не возвращайте столько строк — вы знаете, сколько возвращает ваш запрос?

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

3. Это таблица с примерно 4 столбцами и 3 строками, состояние «ВЫБРАТЬ * ИЗ таблицы». Я почти уверен, что это не вызывает проблем с памятью.

Ответ №1:

По моему прошлому опыту (без документа или чего-либо еще) я бы понял «результирующий набор» как указатель в C. Держу пари, он будет кэшировать некоторые строки из базы данных при выполнении вашего запроса..

Поэтому, если вы закроете соединение, а затем попытаетесь использовать resultset, все эти кэшированные результирующие наборы не будут содержать надлежащей информации и получать следующий кеш и т. Д. В результате это приведет к исключению из памяти..

В любом случае, правильный способ использовать их в java..

 Connection con...
try{
    create connection
    execute query
    use your resultset completely..
}catch(...){
}finally{
    close connection;
}
  

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

Комментарии:

1. большое спасибо за помощь, я думаю, мне придется создать ArrayList в методе и вернуть это. Не уверен, как поддерживать структуру таблицы…

Ответ №2:

Поместите conn.close() в finally блок, чтобы он выполнял событие, если генерируется исключение.

Комментарии:

1. Маловероятно, что это является причиной исключения нехватки памяти

Ответ №3:

всегда, всегда, всегда закрывайте ресурсы вашей базы данных в блоке finally!

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

Комментарии:

1. Из JavaDoc может показаться, что результирующий набор закрывается, если оператор, из которого он был получен, закрывается. Это упоминается в документе для close() методов как ResultSet, так и Statement . Однако такой информации о закрытии соединения нет. Может быть безопасно закрыть соединение, если оператор не закрыт.

2. ОК. Есть ли способ преобразовать результирующий набор в объект Java, сохранив структуру таблицы? Я думаю, я мог бы найти способ с arraylist.

3. @G_H, нет: закрытие соединения закрывает инструкции, открытые этим соединением, и, следовательно, также результирующие наборы. Это явно не упоминается в документах, но в нем упоминается при подключении: «Выполняются инструкции SQL, и результаты возвращаются в контексте соединения» и Connection.close(): «Немедленно освобождает базу данных и ресурсы JDBC этого объекта подключения, а не ждет их автоматического освобождения». Это означает, что оператор также закрывается при закрытии соединения.

4. @MarkRotteveel: Мне было интересно об этом. Однако было бы неплохо внести немного больше ясности в документ. Я видел сайты, которые противоречат этому, и заявляют, что безопасно немедленно закрыть соединение. Есть ли что-нибудь об этом в спецификации JDBC? Я не совсем уверен, что будет считаться «ресурсами базы данных и JDBC» вне объекта подключения. Возможно ли, что некоторые реализации создают отдельное соединение для наборов результатов?

5. В разделе 9.4.4 спецификации JDBC 4.0 говорится: «Все объекты оператора, созданные из данного объекта подключения, будут закрыты при вызове метода close для объекта». Похоже, что соединение действительно должно оставаться открытым. По-видимому, Statement объекты закрываются при сборке мусора (возможно, с помощью finalize), но рекомендуется закрывать их самостоятельно.

Ответ №4:

Помимо закрытия ресурсов в блоке finally, вам также необходимо закрыть your PreparedStatement и your ResultSet . На самом деле, вы не должны возвращать ResultSet и держать его открытым слишком долго. Вместо этого вы могли бы прочитать его в какое-то промежуточное хранилище данных, например List<Object[]> .

С другой стороны, вы не получаете java.lang.OutOfMemoryError , так что, возможно, это сама ваша база данных, у которой закончилась память