2009-11-02 20 views
12

Mój projekt Java (JDK6) używa Spring i JDBCTemplate dla całego dostępu do bazy danych. Niedawno uaktualniliśmy wersję ze Spring 2.5 do Spring 3 (RC1). Projekt nie korzysta z ORM, takiego jak Hibernate ani EJB.Programowanie Java - Spring i JDBCTemplate - Użyj zapytania, queryForList lub queryForRowSet?

Jeśli muszę przeczytać kilka zapisów, a nie jakąś wewnętrzną obróbkę z nich wydaje się, że istnieje kilka (przeciążone) metody: zapytanie, queryForList i queryForRowSet

Jakie powinny być kryteria do korzystania z jednego zamiast drugiego? Czy są jakieś różnice w wydajności? Najlepsze praktyki?

Czy możesz polecić niektóre referencje zewnętrzne do dalszych badań na ten temat?

Odpowiedz

34

Uważam, że standardową metodą dostępu do listy jest stosowanie metod query(), a nie innych metod. Główna różnica między query a innymi metodami polega na tym, że aby obsłużyć zestaw wyników, musisz zaimplementować jeden z interfejsów wywołania zwrotnego (albo RowMapper, RowCallbackHandler lub ResultSetExtractor).

A RowMapper jest prawdopodobnie tym, czego używasz przez większość czasu. Jest używany, gdy każdy wiersz zestawu wyników odpowiada jednemu obiektowi na liście. Trzeba tylko zaimplementować jedną metodę, w której zapełnisz typ obiektu, który trafia do twojego wiersza i zwróci go. Spring ma również BeanPropertyRowMapper, który może zapełniać obiekty na liście, dopasowując nazwy właściwości fasoli do nazw kolumn (NB ta klasa jest dla wygody, a nie dla wydajności).

A RowCallbackHandler jest bardziej przydatna, gdy potrzebujesz, aby wyniki były czymś więcej niż zwykłą listą. Będziesz musiał zarządzać obiektem zwracania samodzielnie używasz tego podejścia. Zwykle używam tego, gdy potrzebuję struktury mapy jako mojego typu zwracanego (tj. Dla zgrupowanych danych dla tabeli drzew lub jeśli tworzę niestandardową pamięć podręczną opartą na kluczu podstawowym).

A ResultSetExtractor służy do kontroli iteracji wyników. Wszczepiasz pojedynczą metodę, która będzie zwracaną wartością połączenia do query. Używam go tylko wtedy, gdy muszę zbudować niestandardową strukturę danych, która jest bardziej złożona w porównaniu z innymi interfejsami wywołania zwrotnego.

Metody o wartości queryForList() są cenne, ponieważ nie trzeba wdrażać tych metod wywoływania zwrotnego. Istnieją dwa sposoby użycia queryForList. Pierwszym z nich jest to, że wyszukujesz tylko jedną kolumnę z bazy danych (na przykład listę łańcuchów), możesz użyć wersji metody, która pobiera klasę jako argument, aby automatycznie wyświetlić listę tylko obiektów tych klas .

Podczas wywoływania innych implementacji queryForList() otrzymasz listę z powrotem z każdym wpisem będącym mapą dla każdej kolumny. Chociaż jest to miłe, ponieważ oszczędza się koszty pisania metod wywoływania zwrotnego, radzenie sobie z tą strukturą danych jest dość nieporęczne. Przekonasz się, że wykonujesz wiele rzutów, ponieważ wartości mapy są typu Object.

ja faktycznie nigdy nie widział queryForRowSet metod stosowanych w środowisku naturalnym. Spowoduje to załadowanie całego wyniku zapytania do obiektu CachedRowSet zwiniętego przez Spring SqlRowSet. Widzę dużą wadę w korzystaniu z tego obiektu, ponieważ jeśli przechodzisz na inne warstwy aplikacji, łączysz te warstwy z implementacją dostępu do danych.

Nie należy zobaczyć jakieś ogromne różnice wydajności pomiędzy tymi połączeniami z wyjątkiem jak wspomniałem z BeanPropertyRowMapper. Jeśli pracujesz z pewną skomplikowaną manipulacją dużym zbiorem wyników, możesz uzyskać trochę wyższego przyrostu wydajności od napisania zoptymalizowanego ResultSetExtractor dla konkretnego przypadku.

Jeśli chcesz dowiedzieć się więcej, skonsultowałbym się z Spring JDBC documentation i JavaDoc for the classes I've mentioned. Możesz również rzucić okiem na niektóre książki z Spring Framework. Chociaż jest to nieco przestarzałe, Java Development with the Spring Framework ma bardzo dobrą sekcję dotyczącą pracy ze strukturą JDBC. Przede wszystkim chciałbym powiedzieć, po prostu spróbuj napisać kod z każdą metodą i zobaczyć, co działa najlepiej dla ciebie.

3

Ponieważ jesteś w cudowny Generics ziemi, co może naprawdę chcesz zrobić, to użyć SimpleJdbcTemplate i wykorzystać swoje query() metody Lists obiektów i queryForObject() dla poszczególnych obiektów. Rozumowanie tego jest po prostu łatwiejsze w użyciu niż te w JdbcTemplate.

+1

AFIK metoda zapytań zgodna z Java 5 jest dostępna w JDBCTemplate również na wiosnę 3 – Adrian

+1

Teraz, gdy sprawdziłem, JdbcTemplate nie używa Generics w Spring 2.5.6, ale jest w wersji 3.0.0. Wyczuwam deprecjację w przyszłości ... :) – Esko

+0

SimpleJdbcTemplate jest teraz rzeczywiście przestarzałe – Helenesh

2

Jeden mały dodatek do doskonałych odpowiedzi powyżej: dodatkowe metody, takie jak queryForInt, queryForLong, queryForMap, queryForObject, itp. Mogą wydawać się czasami dobrym rozwiązaniem, jeśli używasz prostego zapytania i oczekujesz pojedynczego wiersza.

Jednakże, jeśli można odzyskać 0 lub 1 wiersze, metoda queryForList jest generalnie łatwiejsza, w przeciwnym razie trzeba by było uchwycić wyjątek IncorrectResultSizeDataAccessException. Nauczyłem się tego na własnej skórze.