cinci secrete
Improspata relația ta cu API-ul JDBC
JDBC sau Java ™ Database Connectivity, - una dintre cele mai populare pachete în jurul JDK, și totuși, nu mulți dezvoltatori utilizează Java-toate - sau toate dintre cele mai moderne - capacitățile sale. Ted Neward introduce noi caracteristici JDBC, cum ar fi seturi de ResultSet. care în mod automat prevede derularea și actualizarea dinamică a datelor, RowSet. care poate funcționa ca o conexiune bază de date deschisă, și fără ea, și actualizări lot - capacitatea de a efectua mai multe SQL-operatorii cu o transmisie scurtă prin rețea.
Ted Nyuvord. Director, Neward Associates
Despre această serie
Crezi că știi despre Java-programare a tuturor? De fapt, cele mai multe dezvoltatorii sunt razuit doar suprafața platformei Java, examinarea ei doar suficient pentru a efectua munca lor. În această serie, Ted Neward mai adânc în funcționalitatea capacităților platformei Java, dezvăluind fapte puțin cunoscute, care pot ajuta la rezolvarea programarea mai complicate.
Astăzi, multe Java dezvoltatorii interacționează cu API-ul Java Database Connectivity (JDBC) prin intermediul platformei de acces la date, cum ar fi Hibernate sau Spring. Cu toate acestea, JDBC - acest lucru nu este doar un intermediar pentru a se conecta la baza de date. Cu cât îl cunoști, cu atât mai eficient va fi treaba ta la RDBMS.
În acest ciclu de eliberare Cinci secrete ... Voi demonstra mai multe caracteristici noi introduse în perioada dintre JDBC 2.0 și JDBC 4.0. Proiectat pentru problema de programare moderne, aceste caracteristici contribuie la scalabilitatea și performanța aplicațiilor de dezvoltare - soluționarea a două probleme majore cu care se confruntă astăzi Java-programatori.
1. Funcții scalare
Dezvoltarea abilităților de pe acest subiect
Acest material - o parte din calea cunoașterii pentru dezvoltarea abilităților tale. A se vedea articolul Java-programator
Diferite implementari ale SGBD oferi un fel de SQL suport și / sau caracteristici suplimentare proiectate pentru a ușura viața dezvoltatorului. Este bine cunoscut, de exemplu, că SQL este o COUNT operație scalar (). care returnează numărul de rânduri care îndeplinesc anumite criterii de filtrare SQL (de exemplu, atunci când declarațiile). Dar, în alte cazuri, schimbați valorile returnate de SQL, este dificil - și să încerce să facă baza de date pentru a da data și ora curentă poate fi o înnebunitoare chiar mai pacientului (și bold) JDBC-dezvoltator.
În acest sens specificația JDBC oferă un grad de izolare / adaptare pentru implementări diferite baze de date cu funcții scalare. Specificațiile JDBC oferă o listă de operații suportate că șoferii JDBC trebuie să recunoască și să se adapteze după cum este necesar pentru punerea în aplicare specifică a bazei de date. Pentru o bază de date care acceptă Returnează data sau ora curentă poate fi suficientă numai ceea ce este prezentat în Listarea 1.
Listarea 1. Ce oră este?
Lista completă a funcțiilor scalare, care sunt suportate de API-ul JDBC, anexat la caietul de sarcini JDBC (cm. resurse), dar conducătorul auto specific sau baza de date nu poate suporta întreaga listă. Utilizarea DatabaseMetaData obiect. Returnează un obiect Connection. puteți obține o listă cu funcțiile acceptate de această punere în aplicare a JDBC, așa cum se arată în Listarea 2.
Listarea 2. Ce se poate face?
Lista funcțiilor scalare - un șir de caractere (String) valori separate prin virgulă returnate prin diverse metode DatabaseMetaData clasă. De exemplu, apelarea getNumericFunctions () listează toate scalari numerice. Se aplică la String.split) metoda și -vualya (rezultatul! - afișează instantaneu o listă de equals () - testabile.
2. Derulați seturi ResultSet
JDBC procedură foarte comună pentru crearea (sau obținerea existente) obiect de conexiune și de a folosi pentru a crea un obiect Statement. Ca răspuns la expresia Statement SQL SELECT returnează un ResultSet. ResultSet trecut apoi prin în timp (cum ar fi Iterator) ciclu până ResultSet anunță că acesta este gol, corpul buclei preia o coloană la un moment dat de la stânga la dreapta.
Întreaga operațiune este atât de familiară încât este aproape nu se observa: aceasta se realizează automat. Dar, din păcate, nu este în mod necesar.
ResultSet derulabil
Mulți dezvoltatori nu își dau seama că, odată cu anii JDBC în evoluție, dar îmbunătățirile sunt reflectate în noul număr versiune și eliberare. Primul update major, JDBC 2.0, va apărea undeva în zilele de JDK 1.2 eliberare. La momentul scrierii acestui articol este disponibil în JDBC 4.0.
Una dintre cele mai interesante (deși de multe ori ignorate) îmbunătățiri JDBC 2.0 - este abilitatea de a „scroll“ set ResultSet. în măsura în care este necesar, se poate derula înainte / înapoi, sau chiar în ambele direcții în același timp. Cu toate acestea, acest lucru necesită unele informații preliminare - JDBC în apelul în momentul în care obiectul Declarația trebuie spus că este nevoie de o ResultSet derulabil.
Verificați tipul de ResultSet
În cazul în care, în ciuda a ceea ce se spune în DatabaseMetaData. bănuiți că conducătorul auto nu poate suporta seturi de defilare ResultSet. verifica tipul de ResultSet. apelând metoda gettype (). Desigur, cu o astfel de paranoia nu poate fi de încredere și valoarea returnată gettype (). Ei bine, chiar dacă gettype () este situată despre revenirea seturi ResultSet. aparent, ei se ascund de tine.
Dacă driverul JDBC acceptă defilare, declarația va returna un ResultSet derulabil. dar este mai bine pentru a afla înainte rândul său să-l. Suport pentru scroll poate fi găsită prin obiectul DatabaseMetaData. care poate fi accesat prin orice conexiune exprimare. așa cum este descris mai sus.
Avand DatabaseMetaData obiect si cauzand getJDBCMajorVersion (). puteți determina dacă driver-ul suportă, cel puțin, JDBC 2.0 caietul de sarcini. Desigur, șoferul poate minți cu privire la nivelul lor de sprijin pentru această specificație, prin urmare, pentru o mai mare securitate provocări supportsResultSetType metoda (), cu tipul dorit de ResultSet. (Această clasă ResultSet constantă, vom vorbi despre toate aceste valori.)
Listarea 3. dacă defilarea este acceptată?
Solicitați un set de ResultSet derulabil
În cazul în care conducătorul auto a spus „da“ (în caz contrar, este necesar să înlocuiți driver-ul sau baza de date), puteți solicita un ResultSet obiect derulabil. trecere apel Connection.createStatement () sunt doi parametri, așa cum se arată în Listarea 4.
Listarea 4. Vreau să defila!
Când se apelează createStatement () trebuie să fie deosebit de prudenți, deoarece primul și al doilea parametru sunt valori de tip int. (Ce păcat pentru Java 5 nu au fost enumerate tipuri!) Cu createStatement () va rula orice int valoare (inclusiv o valoare eronată a constantei).
Primul parametru care indică dezirabilitatea „prokruchivaemosti» ResultSet. Se poate lua una dintre următoarele trei valori posibile:
- ResultSet.TYPE_FORWARD_ONLY. Aceasta este implicit de tip cursor furtun de incendiu familiar;
- ResultSet.TYPE_SCROLL_INSENSITIVE. un ResultSet permite iterații înainte și înapoi, dar în cazul în care datele sunt într-o bază de date schimbare, ResultSet nu reflectă acest lucru. Poate că acest tip de ResultSet derulabil - cel mai mult în cerere;
- ResultSet.TYPE_SCROLL_SENSITIVE. acest tip de ResultSet nu permite doar iterație bidirecțională, dar, de asemenea, creează o imagine „viu“ a datelor în baza de date, deoarece acestea schimba date.
A doua opțiune este discutată în consiliul următor, așa că acum să-l părăsească.
direcția de parcurgere
Acesta poate fi de asemenea utilă în metode de relativă () și absolută (). deplasează mai întâi cursorul la un anumit număr de linii (forward, dacă valoarea este pozitivă, iar înapoi dacă este negativ), iar al doilea - la o anumită linie ResultSet. indiferent unde este în acest moment. Desigur, numărul liniei curente, pot fi accesate folosind metoda getRow ().
Dacă vă așteptați o mulțime de defilare într-o anumită direcție, poate fi util să se indice această direcție prin apelarea funcției setFetchDirection (). (ResultSet va lucra, indiferent de direcția de defilare, dar știind că în avans va permite optimizarea procesului de recuperare a datelor.)
3. Se poate modifica seturi ResultSet
JDBC suportă nu numai defilare bi-directionala, dar, de asemenea, editarea de seturi ResultSet. Acest lucru înseamnă că, în loc de a crea o nouă declarație SQL pentru a modifica valorile stocate în baza de date, puteți modifica valoarea în interiorul ResultSet. și se va reflecta automat în coloana corespunzătoare a rândului dorit al bazei de date.
Aflați mai multe despre regenerabilitatea ResultSet poate sprijini precum și sprijin și derulare. Există ceva doar, iar al doilea parametru al createStatement operatorului (). În schimb ResultSet.CONCUR_READ_ONLY selectați ca al doilea parametru ResultSet.CONCUR_UPDATEABLE. așa cum se arată în exemplul 5.
Listarea 5. Vreau ResultSet actualizate
În cazul în care conducătorul auto suportă cursoare actualizabile (Aceasta este o altă caracteristică a caietului de sarcini JDBC 2.0, care suportă cea mai mare parte a bazei de date reale), orice valoare dată într-un ResultSet poate fi actualizat prin a merge la rândul și făcând apel o metodă de actualizare. () (Așa cum se arată în exemplul 6). Ca metode de a obține. (Clasa ResultSet). există mai multe metode de actualizare. () ResultSet pentru diferite tipuri de coloane. De exemplu, pentru a schimba o coloană de virgulă mobilă PREȚ. aveți nevoie pentru a apela updateFloat ( „preț“). Cu toate acestea, acest lucru va duce doar la actualizarea valorilor din ResultSet set. Pentru a-l transfera la baza de date, suna updateRow (). În cazul în care utilizatorul a schimbat mintea lui de a schimba prețul, în cancelRowUpdates de apel () va anula orice actualizări în așteptare.
Listarea 6. Cel mai bun mod de a
JDBC 2.0 suportă nu numai de renovare. Pentru a adăuga o nouă linie fără a crea un nou obiect Statement și executarea instrucțiunii INSERT. pur și simplu apel metoda moveToInsertRow (). metoda de actualizare. () Pentru fiecare coloană și metoda în final, insertRow (). Dacă valoarea pentru coloana nu este specificat, se presupune NULL SQL (care poate determina o SQLException excepție. În cazul în care schema bazei de date nu permite valori NULL pentru această coloană).
Desigur, în cazul în care ResultSet acceptă actualizarea rând, aceasta trebuie să sprijine și eliminarea acestuia prin apelarea deleteRow ().
Da, înainte să uit, toate acestea prokruchivaemost și se poate modifica în mod egal aplicabilă unei PreparedStatement (prin trecerea prin aceeași metodă de parametri prepareStatement ()), care este mult mai de preferat la Declarația de obicei din cauza pericolului constant de atacuri SQL injectare.
4. Seturi RowSet
Dacă toată această funcționalitate este cunoscută JDBC cea mai mare parte a deceniului, atunci, de ce majoritatea dezvoltatorilor sunt încă așezat pe o seturi de defilare ResultSet și acces deconectat?
Principalul motiv - scalabilitate. Salvarea numărul minim de conexiuni la baza de date - o condiție esențială pentru susținerea unui număr mare de utilizatori care internetul poate aduce pe web-site-ul companiei. Deoarece defilare și / sau editarea de obiecte ResultSet, de obicei, necesită o conexiune deschisă la rețea, mulți dezvoltatori nu doresc să (sau nu pot) să le utilizeze.
Din fericire, JDBC 3.0 și o alternativă care vă permite să faci multe din lucrurile pe care le puteți face cu ResultSet. lăsând o conexiune deschisă la baza de date.
Ideea este că obiectul RowSet. în esență, este același ResultSet. dar care să permită modelul ca o conexiune, și fără ea. Este suficient pentru a crea un RowSet. arată-l ResultSet. și când este plin, în locul unui ResultSet. așa cum se arată în exemplul 7.
Listarea 7. RowSet în loc ResultSet
JDBC cinci „implementare“ (de exemplu, extensii) interfața RowSet. JdbcRowSet - este realizarea RowSet cu conexiunea; celelalte patru fără conexiune:
- CachedRowSet - este doar un RowSet fără conexiune;
- WebRowSet - o subclasă de CachedRowSet. care „știe“ cum de a converti rezultatele la XML și înapoi din nou;
- JoinRowSet - l WebRowSet. care, de asemenea „poate“ genera SQL echivalent TE fără a fi nevoie de a se conecta la baza de date;
- FilteredRowSet - l WebRowSet. posibilitatea de a filtra, de asemenea, datele fără a fi nevoie să se conecteze la baza de date.
clase RowSet - un module complete de JavaBean care susțin evenimente, cum ar fi ascultarea, astfel încât orice modificări ale RowSet pot fi fixate, să ia în considerare și să adopte, dacă este necesar. De fapt, un RowSet poate controla chiar toată acțiunea asupra bazei de date, dacă specificați proprietățile sale nume de utilizator. Parola. URL și DatasourceName (adică se creează o conexiune utilizând DriverManager.getConnection ()) sau DataSource (care, probabil, pot fi obținute prin JNDI). Apoi, puteți comanda executarea instrucțiunilor SQL în proprietatea de comandă. apelați Execute () și să înceapă să lucreze cu rezultate - este necesar nimic altceva.
Realizarea RowSet. de obicei, furnizate de către conducătorul auto JDBC, numele real și / sau pachet va depinde de driverul JDBC. Implementari RowSet devin o parte a distribuției standard, începând cu Java 5, astfel încât doar suficient pentru a crea. RowsetImpl () și locul de muncă. (În cazul puțin probabil că nu este în driver-ul, Sun oferă o implementare de referință, a se vedea link-ul în resurse.).
5. Lot Actualizări
În ciuda tuturor utilitatea lor, opțiunile RowSet, uneori, nu îndeplinesc toate cerințele, și trebuie să ne întoarcem la scrierea directă SQL-operatorii. În astfel de situații, în special atunci când o mulțime de muncă, este posibil să se evalueze posibilitatea unei actualizări de lot, și anume executa mai multe SQL-operatori pe baza de date într-o singură interacțiune în întreaga rețea.
Pentru a determina dacă driver-ul suportă actualizări lot JDBC, apel DatabaseMetaData.supportsBatchUpdates (). și veți obține un răspuns clar. În cazul în care sunt acceptate actualizări lot (acest lucru poate indica altceva decât SELECT -vyrazheny), face un viraj și să-l într-o singură lovitură, așa cum se arată în Listarea 8.
Listarea 8. Prinde, baza de date!
setAutoCommit () apel este necesară, deoarece driver-ul implicit va încerca să execute fiecare operator în parte. Restul codului este foarte simplu: de obicei interogări SQL folosind expresii Statement sau PreparedStatement. dar executeBatch () metodă se numește în loc de a executa metoda (). că, în loc de doar trimite o solicitare, se pune într-o coadă.
Când totul este gata, trimite întregul loc într-o bază de date prin apelarea executeBatch metoda () - returnează o matrice de numere întregi care conțin aceleași rezultate ca și atunci când se utilizează metoda executeUpdate ().
concluzie
API-ul JDBC, unul dintre pilonii Java de programare, un Java dezvoltator ar trebui să știe ca „Tatăl nostru.“ Este amuzant că cei mai mulți programatori nu ține pasul cu îmbunătățirile API, și ca urmare a acestor dezvoltatori lipsește o oportunitate de a economisi timp prin utilizarea tehnicilor descrise în acest articol.
Desigur, dacă să utilizeze noile caracteristici JDBC, decideți. Aspectul principal care urmează să fie abordate - este scalabilitatea sistemului pe care lucrați. Este necesar de a construi mai mult, cu atât mai limitate nu va avea acces la baza de date și, prin urmare, cu atât mai mare necesitatea de a reduce traficul de rețea să-l. În acest caz, asistenții vor rowsets RowSet. provocări și actualizări lot scalară. În alte cazuri, încercați derularea și actualizate set ResultSet (care nu consumă atât de mult de memorie ca seturi RowSet) și măsura impactul acestora asupra scalabilitate. Este posibil ca aceasta nu va fi la fel de mare ca ar putea părea.
În continuare, în ciclul de 5 ... secrete. steaguri linie de comandă.