@dndred

jdbc — два запроса в одном соединении

Здравствуйте!
Начал изучать Java и уперся в проблему работы с базой данных — не могу выполнить второй sql запрос в одном соединении, имея открытый первый. В документации по JDBC написано, что для этого следует использовать другой экземпляр объекта PreparedStatement, но мне это не помогает — при выполнении второго запроса, недочитанный ResultSet первого закрывается.
                conn = DriverManager.getConnection(
                                strURL + "?lc_ctype=WIN1251",properties);
                PreparedStatement q1 = conn.prepareStatement("select * from params");
                ResultSet r1 = q1.executeQuery();
                PreparedStatement q2 = conn.prepareStatement("select * from clients");
                ResultSet r2 = q2.executeQuery();
                r1.next();//Тут программа вываливается с ошибкой org.firebirdsql.jdbc.FBSQLException: The result set is closed
                r1.getObject(1); 
                r2.next();
                r2.getObject(1);

Полный текст на http://pastebin.com/
Неужели нужно открывать новое соединение на каждый запрос? Или я что-то не так делаю?
Заранее спасибо!
  • Вопрос задан
  • 8190 просмотров
Пригласить эксперта
Ответы на вопрос 7
@sergei-grigorev
Нет, не нужно поднимать новое соединение на каждый запрос. Нужно закрывать имеющиеся statements перед вызовом новых. Просто в данном случае, у тебя одновременно открыто два разных запроса, один из которых в пакетном режиме подтягивает данные из одной таблицы, а второй — подтягивает совершенно другие данные из второй таблицы. Одновременно это быть не может. В данном случае вам действительно потребуется два коннекта (используйте пул соединений для более эффективной работы). Либо вы можете подтянуть данные сначала из одного запроса, закрыть PrepareStatement и ResultSet, и только затем уже подтягивать данные из второй таблицы.
Ответ написан
Snowindy
@Snowindy
Скорее всего, вам нужно будет получить другое соединение для второго запроса. Но я бы так не делал.
Если вам надо одновременно читать из двух мест в одной базе, значит проблема в дизайне. Вероятно, стоит применить одно из:
1) написать один JOIN для двух таблиц и вернуть его
2) Начитать первый результат в память и работать с этими данными во время итераций по второму
3) Использовать хранимую процедуру в БД, которая сделает всю логику и вернет результат.
Ответ написан
@1nd1go
В документации написано, что Statement
By default, only one ResultSet object per Statement object can be open at the same time.

Therefore, if the reading of one ResultSet object is interleaved with the reading of another, each must have been generated by different Statement objects.

All execution methods in the Statement interface implicitly close a statment's current ResultSet object if an open one exists
Ответ написан
@1nd1go
Непонятно как комментарий к моему же ответу так глубоко упал…

Попробуйте: Statement.getResultSet() вместо Statement.executeQuery()
Ответ написан
@ComodoHacker
Эту возможность прежде всего должна поддерживать используемая СУБД. Ну и драйвер соответственно. Например в MSSQL она появилась не так давно, с 2005 версии. Насчет вашего Firebird определенно сказать не могу, копайте доки.
Ответ написан
Beholder
@Beholder
Всё сильно зависит от типа базы данных и JDBC-драйвера, но обычно такие фокусы не дозволяются. Ну подумайте — передавать по одному TCP-соединению одновременно сразу два разных набора данных — это хоть и реализуемо в принципе, но обычно авторы этим не заморачиваются.
Ответ написан
Комментировать
@dkurilenko
использовать пул соединений и доставать соединения из пула для каждого запроса. Затем класть обратно.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы