#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
, так что, возможно, это сама ваша база данных, у которой закончилась память