Rodzaje wypowiedzi
Widzieliśmy już najprostszy interfejs Statement . I chociaż całkiem nadaje się do pracy, nie nadaje się tak dobrze do złożonych zapytań. W niektórych źródłach wyrażana jest opinia, że w ogóle nie trzeba używać Statement – zamiast tego odpowiednie są bardziej złożone i bogatsze funkcjonalnie interfejsy.
- Przygotowane oświadczenie
- CallableStatement
Powstaje całkiem rozsądne pytanie - po co potrzebne są te interfejsy? Rozwiążmy to.
Najpierw przyjrzymy się interfejsowi PreparedStatement i innym funkcjom JDBC. Do interfejsu CallableStatement wrócimy później - jego użycie, po pierwsze, nie jest tak powszechne, a po drugie, po przemyśleniu wszystkiego, rozmowa może być już dość krótka.
Również PreparedStatement jest bardzo pomocne w popularnym podejściu do hakowania baz danych o nazwie SQL Injection.
Ale o tym trochę później.
Przygotowane oświadczenie
Jeśli spróbujesz przetłumaczyć nazwę PreparedStatement , możesz otrzymać coś w rodzaju „prepared statement”. Najważniejszym słowem jest tutaj „przygotowany”. Co to jest „gotowość”?
Zanim rozważymy ten problem, proponuję zobaczyć dość ważny punkt z punktu widzenia wygody, który występuje bardzo często. Tak więc w niektórych aplikacjach musimy wstawić dane kontaktowe do tabeli KONTAKT. W tym celu musimy przygotować takie zapytanie:
INSERT INTO JC_CONTACT (FIRST_NAME, LAST_NAME, PHONE, EMAIL) VALUES (‘Harry’,'Potter','+79112345678','harry@example.com);
Na pierwszy rzut oka wydaje się, że wszystko nie jest takie trudne i przerażające. Musimy napisać kod, który zbierze potrzebny nam ciąg z parametrów: imię, nazwisko, adres i numer telefonu. Musisz tylko pamiętać, że wszystkie dane łańcuchowe muszą być otoczone pojedynczym cudzysłowem.
Jeśli zrobimy to w osobnej funkcji, otrzymamy coś takiego:
public String buildInsert(String firstName,, String lastName, String phone, String email) {
String sql = "INSERT INTO JC_CONTACT (FIRST_NAME, LAST_NAME, PHONE, EMAIL) “+
”VALUES ('" + firstName + "','" + lastName + "','" + phone + "','" + email + ")";
return sql;
}
Imię, nazwisko, numer telefonu i adres przekazujemy do funkcji parametru w formularzu iz nich tworzymy ciąg zapytania SQL. Cytaty trochę psują obraz, ale jak na razie nie jest to straszne.
Ok, a co z liczbami? Nie muszą być otoczone cytatami. Opanki, w jednym przypadku potrzebujesz cytatów, w drugim nie. Sytuacja się komplikuje.
Teraz dodajmy jeszcze jeden problem - co jeśli w ciągu znaków znajduje się zwykły cytat (a nawet nie jeden)? Musisz najpierw wyszukać takie cytaty i je przetworzyć. Mdaaa. W jakiś sposób zaczynamy czuć się nieswojo.
Jeśli dodamy teraz przetwarzanie daty, to zadanie staje się zupełnie nudne - trzeba wykonać ogromną ilość pracy. Daty są ogólnie nieprzyjemne - różne serwery SQL akceptują różne formaty dat.
Więc co widzimy? Jeśli musimy użyć parametrów wewnątrz zapytania, to ręczne budowanie zapytania staje się bardzo nieprzyjemne. I nie tylko nieprzyjemne - powiedziałbym nawet, że nudne. Istnieje ogromna liczba przypadków do rozważenia, a to jest strasznie nudna praca. W zasadzie to właśnie dla takich przypadków zaproponowano interfejs PreparedStatement .
Ta prośba umożliwia wykonanie dwóch czynności:
- Przygotuj wcześniej zapytanie ze wskazaniem miejsc, w których parametry zostaną podstawione
- Ustaw parametry określonego typu, a następnie wykonaj zapytanie z już ustawionymi parametrami
Przykład przygotowanej instrukcji
Struktura PreparedStatement dla naszej opcji ustawiania parametrów będzie wyglądać następująco:
// Example variables
String firstName = "Harry";
String lastName = "Potter";
String phone = "+12871112233";
String email = "harry@example.com";
// Request with indication of places for parameters in the form of "?"
String sql = "INSERT INTO JC_CONTACT (FIRST_NAME, LAST_NAME, PHONE, EMAIL) VALUES (?, ?, ?, ?)";
// Create a request. The con variable is an object of type Connection
PreparedStatement stmt = con.prepareStatement(sql);
// Set parameters
stmt.setString(1, firstName);
stmt.setString(2, lastName);
stmt.setString(3, phone);
stmt.setString(4, email);
// Execute the request
stmt.executeUpdate();
Jak widać, wszystko jest dość proste.
Po pierwsze, podczas pisania zapytania SQL miejsca, w których parametry będą musiały zostać zastąpione, są zapisywane znakami zapytania - „?”.
Po drugie, żądanie jest tworzone przez wywołanie metody con.prepareStatement() .
Po trzecie, ustawienie parametrów odbywa się poprzez wskazanie liczby i wartości. Należy pamiętać, że liczba parametrów zaczyna się od 1, a nie od 0, do czego jesteśmy przyzwyczajeni podczas pracy z tablicami i kolekcjami.
Interfejs PreparedStatement zawiera metody ustawiania łańcuchów — setString() , ustawiania liczb — setInt() , setLong() , setDouble() , ustawiania dat — setDate() . I bardziej złożone typy - można to zobaczyć w dokumentacji.
Po czwarte, wywołanie stmt.executeUpdate() jest już wykonywane bez określenia ciągu zapytania.
Gorąco polecam zaprzyjaźnienie się z PreparedStatement - to bardzo skuteczne narzędzie.