2012-04-02 20 views
6

Według documentation dla getResultSet w java.sql.Statement, to mówi:getResultSet() „powinna być wywoływana tylko raz w wyniku”

Pobiera aktualny wynik jako obiekt ResultSet. Ta metoda powinna być wywołana tylko jeden raz na wynik.

Używając kodu testowego, wpadłem executeQuery() i kilka połączeń do getResultSet() i zauważył, że ResultSet powrócił wskazał do tego samego obiektu. Zgaduję, że to nie jest zwracanie innego ResultSet, które trzeba zamknąć indywidualnie. Ale oczywiście może to być unikalne dla moich sterowników JDBC.

Patrząc na documentation dla ResultSet mówi:

domyślny obiekt ResultSet nie mogą być aktualizowane i zawiera kursor, który porusza się do przodu tylko . W związku z tym można go powtórzyć tylko raz i tylko od pierwszego do ostatniego wiersza.

Wydaje się, że to dobry powód, dla którego nie jest dobrym pomysłem wielokrotne wywoływanie, ponieważ może to doprowadzić do pewnej "sytuacji". Jeśli to był jedyny powód, czułem, że mogli to właśnie powiedzieć, więc myślę, że może być coś więcej niż to.

Więc czy ktoś wie dlaczego nie powinno się nazywać getResultSet więcej niż raz w wyniku? Ta question jest tym, co mnie zaciekawiło.

+1

Nie publikujesz tego jako odpowiedzi, ponieważ jest to tylko przeczucie, ale podejrzewam, że jest to sposób, aby dać trochę swobody programistom sterowników JDBC, pozwalając im nie definiować, co się stanie, gdy zadzwonisz do niego więcej niż raz. W twoim konkretnym przypadku działa, ale jeśli kiedykolwiek zmienisz sterowniki JDBC, może tak się nie stać. –

+1

Myślę, że jest to równie proste: obiekt ResultSet ma stan. Istnieje tylko jeden obiekt ResultSet jako członek oświadczenia. Uzyskanie obiektu nie powoduje ponownego wykonania instrukcji. Uzyskanie obiektu po raz drugi nie gwarantuje, że będzie w tym samym stanie, co pierwszy, jeśli zmodyfikowałeś coś po pierwszym otrzymaniu. Jest to po prostu ostrożność. Patrząc na sterownik jdbc Postres (org.postgresql.jdbc2.AbstractJdbc2Statement), widzimy, że wewnętrznie wykonuje wiele takich połączeń: return (result! = Null && result.getResultSet()! = Null); – Glenn

Odpowiedz

4

Przedmiotem ResultSet jest dostarczane przez interfejs Java JDBC - nie zapewniają realizacji. Nawet jeśli szczególności kod bazy danych i związane z nimi sterowniki wdrożyć ResultSet dzięki czemu może nazywają to wiele razy w rezultacie, jeśli zależy na takie zachowanie, które jest poza zamówienia, jesteś na pewno igranie z ogniem.

Możliwym powodem, że kontrakt został napisany z linią this method should be called only once per result jest ze względów wydajności. Utworzenie ResultSet najprawdopodobniej spowoduje wywołanie RPC JDBC do bazy danych, a autorzy specyfikacji JDBC chcieli zniechęcić do wielokrotnych podróży w obie strony. Mogli nie chcieć zmusić wykonawców do skutecznej ochrony przed wielokrotnymi połączeniami na wynik. Ponownie, nawet jeśli twoja baza danych chroni przed tym zachowaniem, nie oznacza to, że będzie następna.

Większość implementacji ResultSet utrzymuje również połączenie z bazą danych, dzięki czemu po uzyskaniu określonych pól (takich jak duże obiekty blob) może oddzwonić do bazy danych, aby uzyskać dane. Mając wiele połączeń otwartych lub (co gorsza) przy użyciu tego samego połączenia z wielu ResultSet obiektów byłoby bardzo niebezpieczne/mylące.

Mogli też martwić się o dwie części kodu wywołującego dwa razy getResultSet() i zwrócono referencje do tego samego niezsynchronizowanego obiektu. Spowoduje to zamieszanie po wywołaniu next() i nadpisanie obiektu wieloma odwołaniami.

Ja oczywiście spekulacje, ale mam nadzieję, że to pomaga.

+0

Zdecydowanie pomocny! Jeśli dobrze pamiętam, zamknięcie 'ResultSet' nie powoduje zamknięcia żadnych potencjalnych obiektów blob. Jestem nieco zdezorientowany trzecim akapitem dotyczącym wielu połączeń. Czy "Resultset" nie użyłby tego samego "Connection" do pobrania jakichkolwiek danych z bazy danych? Ponadto jestem niejasny, dlaczego to samo 'Połączenie' z wielu' ResultSet' jest złe - jestem pewien, że jest coś oczywistego, którego nie widzę. Dodatkowo, jeśli możesz podać przykład (nawet jeśli chodzi o określone sterowniki JDBC), gdzie dwukrotne wywoływanie 'getResult' będzie problematyczne, myślę, że byłoby to idealną odpowiedzią. – nevets1219

+0

Po trzecim akapicie mówię tylko, że zarządzanie połączeniami to problem. Posiadanie wielu kopii obiektu 'Connection' lub jeśli dwa wątki miały' ResultSet' i były wykonywane na tym samym niezsynchronizowanym 'Połączeniu', byłoby to niebezpieczne. – Gray

+0

Pod względem przykładu nie mam na to czasu. Chodzi o naruszenie umowy. Postgres może zmodernizować swój sterownik i nieznacznie zmienić jego zachowanie, ale nadal będzie spełniał warunki umowy, a Twój kod złamie się, jeśli będziesz musiał polegać na wielu połączeniach do pracy. To kwestia zasad. – Gray

Powiązane problemy