Vodič kroz Jdbi

1. Uvod

U ovom ćemo članku pogledati kako upiti relacijsku bazu podataka pomoću jdbi.

Jdbi je Java biblioteka otvorenog koda (Apache licenca) koja koristi lambda izraze i refleksiju kako bi pružila prijateljskije sučelje više razine od JDBC-a za pristup bazi podataka.

Jdbi, međutim, nije ORM; iako ima opcijski modul mapiranja SQL objekata, nema sesiju s priloženim objektima, sloj neovisnosti baze podataka i bilo koja druga zvona i tipike uobičajenog ORM-a.

2. Jdbi postavljanje

Jdbi je organiziran u jezgru i nekoliko opcijskih modula.

Da bismo započeli, samo moramo uključiti temeljni modul u naše ovisnosti:

  org.jdbi jdbi3-jezgra 3.1.0 

Tijekom ovog članka prikazat ćemo primjere korištenja baze podataka HSQL:

 org.hsqldb hsqldb 2.4.0 test 

Možemo pronaći najnoviju verziju jdbi3-jezgra, HSQLDB i ostali Jdbi moduli na Maven Central.

3. Povezivanje s bazom podataka

Prvo se moramo povezati s bazom podataka. Da bismo to učinili, moramo odrediti parametre veze.

Polazna točka je Jdbi razred:

Jdbi jdbi = Jdbi.create ("jdbc: hsqldb: mem: testDB", "sa", "");

Ovdje navodimo URL veze, korisničko ime i, naravno, lozinku.

3.1. Dodatni parametri

Ako trebamo navesti druge parametre, koristimo preopterećenu metodu prihvaćanja a Svojstva objekt:

Svojstva svojstva = new Svojstva (); properties.setProperty ("korisničko ime", "sa"); properties.setProperty ("lozinka", ""); Jdbi jdbi = Jdbi.create ("jdbc: hsqldb: mem: testDB", svojstva);

U ovim smo primjerima spremili Jdbi primjer u lokalnoj varijabli. To je zato što ćemo ga koristiti za slanje izjava i upita u bazu podataka.

Zapravo, samo pozivanje stvoriti ne uspostavlja nikakvu vezu s DB-om. Samo sprema parametre veze za kasnije.

3.2. Korištenje a Izvor podataka

Ako se na bazu podataka povežemo pomoću a Izvor podataka, kao što je to obično slučaj, možemo se poslužiti odgovarajućim stvoriti preopterećenje:

Jdbi jdbi = Jdbi.create (izvor podataka);

3.3. Rad s ručkama

Stvarne veze s bazom podataka predstavljene su primjerima Ručka razred.

Najlakši način rada s ručkama i automatskim zatvaranjem je pomoću lambda izraza:

jdbi.useHandle (handle -> {doStuffWith (handle);});

Mi zovemo useHandle kad ne moramo vratiti vrijednost.

Inače, koristimo withDrška:

jdbi.withHandle (handle -> {return computeValue (handle);});

Također je moguće, iako se ne preporučuje, ručno otvoriti ručicu veze; u tom slučaju moramo ga zatvoriti kad završimo:

Jdbi jdbi = Jdbi.create ("jdbc: hsqldb: mem: testDB", "sa", ""); probajte (Handle handle = jdbi.open ()) {doStuffWith (handle); }

Srećom, kao što vidimo, Ručka provodi Može se zatvoriti, tako da se može koristiti s isprobavanjem resursa.

4. Jednostavne izjave

Sad kad znamo kako doći do veze, pogledajmo kako je koristiti.

U ovom ćemo odjeljku stvoriti jednostavnu tablicu koju ćemo koristiti u cijelom članku.

Za slanje izjava poput stvoriti tablicu u bazi podataka koristimo izvršiti metoda:

handle.execute ("izradi projekt tablice" + "(identitet cijelog broja ID-a, ime varchar (50), url varchar (100))");

izvršiti vraća broj redaka na koje je izjava utjecala:

int updateCount = handle.execute ("umetni u vrijednosti projekta" + "(1, 'tutoriali', 'github.com/eugenp/tutorials')"); assertEquals (1, updateCount);

Zapravo, izvršenje je samo praktična metoda.

Složenije slučajeve upotrebe razmotrit ćemo u kasnijim odjeljcima, no prije nego što to učinimo, moramo naučiti kako iz baze podataka izvaditi rezultate.

5. Upit o bazi podataka

Najjednostavniji izraz koji daje rezultate iz DB-a je SQL upit.

Da bismo izdali upit s Jdbi Handle-om, moramo, barem:

  1. stvoriti upit
  2. odaberite način predstavljanja svakog retka
  3. ponovite rezultate

Sada ćemo pogledati svaku od gornjih točaka.

5.1. Izrada upita

Neiznenađujuće, Jdbi predstavlja upite kao primjerke Upit razred.

Jednu možemo dobiti iz ručke:

Upit upita = handle.createQuery ("odaberi * iz projekta");

5.2. Mapiranje rezultata

Jdbi apstrahira daleko od JDBC-a Postavi rezultat, koji ima prilično glomazan API.

Stoga nudi nekoliko mogućnosti za pristup stupcima koji proizlaze iz upita ili neke druge naredbe koja vraća rezultat. Sad ćemo vidjeti one najjednostavnije.

Svaki red možemo predstaviti kao kartu:

query.mapToMap ();

Ključevi karte bit će odabrani nazivi stupaca.

Ili, kada upit vraća jedan stupac, možemo ga preslikati na željeni tip Java:

handle.createQuery ("odaberite ime iz projekta"). mapTo (String.class);

Jdbi ima ugrađene mape za mnoge uobičajene razrede. Oni koji su specifični za neku knjižnicu ili sustav baza podataka pružaju se u zasebnim modulima.

Naravno, također možemo definirati i registrirati svoje mapere. O tome ćemo u kasnijem odjeljku.

Konačno, možemo mapirati redove u grah ili neku drugu prilagođenu klasu. Ponovno ćemo vidjeti naprednije opcije u posebnom odjeljku.

5.3. Iteracija nad rezultatima

Nakon što smo odlučili kako mapirati rezultate pozivanjem odgovarajuće metode, dobivamo a RezultatIterati objekt.

Tada ga možemo koristiti za ponavljanje rezultata, jedan po jedan redak.

Ovdje ćemo pogledati najčešće opcije.

Rezultate možemo samo prikupiti na popisu:

Popis rezultati = query.mapToMap (). list ();

Ili drugome Kolekcija tip:

Navesti rezultate = query.mapTo (String.class) .collect (Collectors.toSet ());

Ili možemo ponoviti rezultate kao tok:

query.mapTo (String.class) .useStream ((Stream stream) -> {doStuffWith (stream)});

Ovdje smo izričito upisali potok varijabla za jasnoću, ali to nije potrebno učiniti.

5.4. Dobivanje jednog rezultata

Kao poseban slučaj, kada očekujemo ili nas zanima samo jedan red, na raspolaganju imamo nekoliko namjenskih metoda.

Ako želimo najviše jedan rezultat, možemo koristiti findFirst:

Neobvezno prvo = query.mapToMap (). findFirst ();

Kao što vidimo, vraća Neobvezno vrijednost koja je prisutna samo ako upit vraća barem jedan rezultat.

Ako upit vraća više od jednog retka, vraća se samo prvi.

Ako umjesto toga, želimo jedan i samo jedan rezultat, koristimo findOnly:

Date onlyResult = query.mapTo (Date.class) .findOnly ();

Napokon, ako postoji nula rezultata ili više njih, findOnly baca an IllegalStateException.

6. Parametri vezanja

Često, upiti imaju fiksni dio i parametrizirani dio. To ima nekoliko prednosti, uključujući:

  • sigurnost: izbjegavanjem spajanja nizova sprečavamo ubrizgavanje SQL-a
  • jednostavnost: ne moramo se sjećati točne sintakse složenih vrsta podataka, poput vremenskih oznaka
  • izvedba: statički dio upita može se jednom raščlaniti i predmemorirati

Jdbi podržava i pozicijske i imenovane parametre.

Pozicijske parametre umetamo kao upitnike u upit ili izjavu:

Upit positionalParamsQuery = handle.createQuery ("odaberite * iz projekta gdje je ime =?");

Imenovani parametri umjesto toga počinju dvotačkom:

Upit namedParamsQuery = handle.createQuery ("odaberite * iz projekta gdje je url poput: pattern");

U oba slučaja, da bismo postavili vrijednost parametra, koristimo jednu od varijanti vezati metoda:

positionalParamsQuery.bind (0, "vodiči"); namedParamsQuery.bind ("obrazac", "% github.com / eugenp /%");

Imajte na umu da, za razliku od JDBC, indeksi počinju na 0.

6.1. Povezivanje više imenovanih parametara odjednom

Također možemo povezati više imenovanih parametara zajedno pomoću objekta.

Recimo da imamo ovaj jednostavan upit:

Upit upita = handle.createQuery ("odaberite ID iz projekta gdje je ime =: ime i url =: url"); Parametri karte = novi HashMap (); params.put ("ime", "ODMOR s proljećem"); params.put ("url", "github.com/eugenp/REST-With-Spring");

Tada, na primjer, možemo koristiti kartu:

query.bindMap (params);

Ili možemo koristiti objekt na razne načine. Evo, na primjer, vežemo objekt koji slijedi JavaBean konvenciju:

query.bindBean (paramsBean);

Ali mogli bismo povezati i polja ili metode objekta; za sve podržane opcije pogledajte Jdbi dokumentaciju.

7. Izdavanje složenijih izjava

Sad kad smo vidjeli upite, vrijednosti i parametre, možemo se vratiti izjavama i primijeniti isto znanje.

Podsjetimo da je izvršiti metoda koju smo ranije vidjeli samo je zgodan prečac.

Zapravo, slično upitima, DDL i DML izrazi predstavljeni su kao primjerci klase Ažuriranje.

Jednu možemo dobiti pozivom metode createUpdate na dršci:

Ažuriranje ažurirati = handle.createUpdate ("INSERT IN TO PROJECT (NAME, URL) VALUES (: name,: url)");

Zatim, na ažuriranje imamo sve metode vezivanja koje imamo u a Upit, tako da se odjeljak 6. odnosi i na ažuriranja.url

Izjave se izvršavaju kad nazovemo, iznenadimo, izvršiti:

int redovi = update.execute ();

Kao što smo već vidjeli, vraća broj zahvaćenih redaka.

7.1. Izdvajanje vrijednosti stupca s automatskim povećanjem

Kao poseban slučaj, kada imamo izraz za umetanje s automatski generiranim stupcima (obično automatsko povećanje ili sekvence), možda ćemo htjeti dobiti generirane vrijednosti.

Onda, ne zovemo izvršiti, ali executeAndReturnGeneratedKeys:

Ažuriranje ažurirati = handle.createUpdate ("INSERT INTO PROJECT (NAME, URL)" + "VRIJEDNOSTI ('tutoriali', 'github.com/eugenp/tutorials')"); ResultBearing generatedKeys = update.executeAndReturnGeneratedKeys ();

ResultBearing je isto sučelje koje implementira Upit razred što smo već vidjeli, pa već znamo kako ga koristiti:

generatedKeys.mapToMap () .findOnly (). get ("id");

8. Transakcije

Transakcija nam je potrebna kad god moramo izvršiti više izjava kao jednu, atomsku operaciju.

Kao i kod ručica veze, i transakciju uvodimo pozivanjem metode s zatvaranjem:

handle.useTransaction ((Ručka h) -> {haveFunWith (h);});

I, kao i kod ručki, transakcija se automatski zatvara kad se zatvaranje vrati.

Međutim, moramo izvršiti ili vratiti transakciju prije povratka:

handle.useTransaction ((Ručka h) -> {h.execute ("..."); h.commit ();});

Ako se, pak, izuzme izuzeće iz zatvaranja, Jdbi automatski vraća transakciju.

Kao i kod ručki, i mi imamo posvećenu metodu, inTransaction, ako želimo nešto vratiti iz zatvaranja:

handle.inTransaction ((Ručka h) -> {h.execute ("..."); h.commit (); return true;});

8.1. Ručno upravljanje transakcijama

Iako se u općem slučaju to ne preporučuje, možemo i mi početi i Zatvoriti transakcija ručno:

handle.begin (); // ... handle.commit (); handle.close ();

9. Zaključci i daljnje čitanje

U ovom uputstvu predstavili smo jezgru Jdbija: upiti, izvodi i transakcije.

Izostavili smo neke napredne značajke, poput prilagođenog mapiranja redaka i stupaca i skupne obrade.

Također nismo razgovarali ni o jednom opcijskom modulu, ponajviše o proširenju SQL Object.

Sve je detaljno predstavljeno u Jdbi dokumentaciji.

Provedbu svih ovih primjera i isječaka koda možete pronaći u projektu GitHub - ovo je Maven projekt, pa bi ga trebalo lako uvesti i pokrenuti kao što jest.