2012-04-02 3 views
6

Согласно documentation для getResultSet в java.sql.Statement, он говорит:getResultSet() «должна вызываться только один раз в результате»

Возвращает текущий результат в виде объекта ResultSet. Этот метод должен вызываться только один раз за каждый результат.

Используя некоторый тестовый код, я побежал executeQuery() и несколько вызовов getResultSet() и отметил, что ResultSet вернулся указал на тот же объект. Поэтому я предполагаю, что он не возвращает другой ResultSet, который вам нужно будет закрыть индивидуально. Но, конечно, это может быть уникальным для моих драйверов JDBC.

Глядя на documentation для ResultSet он говорит:

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

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

Так кто-нибудь знает, почему нельзя звонить getResultSet более одного раза за результат? Это question - это то, что заставило меня любопытствовать в первую очередь.

+1

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

+1

Я бы подумал, что это так же просто: объект ResultSet имеет состояние. В качестве члена Заявления есть только один объект ResultSet. Получение объекта не повторяет выполнение инструкции. Получение объекта во второй раз не гарантируется в том же состоянии, что и первый, если вы изменили что-то после первого получения. Так что это просто предостережение. Заглядывая в драйвер Postgres jdbc (org.postgresql.jdbc2.AbstractJdbc2Statement), мы видим, что внутри он делает много таких вызовов: return (result! = Null && result.getResultSet()! = Null); – Glenn

ответ

4

Объект ResultSet - это интерфейс, предоставляемый Java JDBC - они не обеспечивают реализацию. Несмотря на то, что ваш конкретный код базы данных и связанные с ним драйверы реализуют ResultSet, так что вы можете указать называть его несколько раз за каждый результат, если вы зависите от такого поведения, которое находится за пределами контракта, вы, безусловно, играете с огнем.

Одна из возможных причин того, что договор был составлен по линии this method should be called only once per result по соображениям эффективности. Построение ResultSet, скорее всего, вызовет вызов JCBC RPC в базу данных, и авторы спецификации JDBC хотели бы отбить многократные поездки. Возможно, они не захотели заставить исполнителей эффективно защищать от нескольких вызовов за результат. Опять же, несмотря на то, что ваша база данных защищает от этого поведения, это не значит, что следующая будет.

Большинство версий ResultSet также поддерживают соединение с базой данных, так что, когда вы получаете определенные поля (такие как большие капли), он может перезвонить в базу данных, чтобы получить данные. Наличие нескольких соединений, открытых или (хуже) с использованием одного и того же соединения из нескольких объектов, будет очень опасным/запутанным.

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

Я, конечно, размышляю, но надеюсь, что это поможет.

+0

Определенно полезно! Если я правильно помню, закрытие 'ResultSet' не закрывает никаких потенциальных блобов. Я немного запутался в третьем абзаце, касающемся нескольких соединений. Не будет ли 'ResultSet' использовать одно и то же« соединение »для извлечения любых данных из базы данных? Кроме того, я не понимаю, почему то же самое «соединение» из нескольких «ResultSet» плохое - я уверен, что есть что-то очевидное, что я пропускаю. Кроме того, если вы можете предоставить пример (даже если это для конкретных драйверов JDBC), где вызов вызова getResult дважды будет проблематичным, я думаю, что это был бы идеальный ответ. – nevets1219

+0

Re 3-й абзац, я просто говорю, что управление соединениями является проблемой. Имея несколько копий объекта «Connection» или если каждый из двух потоков имел «ResultSet» и выполнял операции с тем же несинхронизированным «Connection», это было бы опасно. – Gray

+0

Что касается примера, у меня нет на это времени. Речь идет о нарушении договора. Postgres может обновить свой драйвер и немного изменить поведение, но выполнить контракт, и ваш код сломается, если вы зависете от нескольких вызовов для работы. Это принципиально. – Gray

Смежные вопросы