Sprievodca po Jdbi
1. Úvod
V tomto článku sa pozrieme na to, ako dopytovať relačnú databázu pomocou jdbi.
Jdbi je open source knižnica Java (licencia Apache), ktorá používa výrazy lambda a reflexiu na zabezpečenie priateľskejšieho rozhrania na vyššej úrovni ako JDBC na prístup k databáze.
Jdbi však nie je ORM; aj keď má voliteľný modul mapovania objektov SQL, nemá reláciu s pripojenými objektmi, vrstvu nezávislosti databázy a iné zvončeky a píšťalky typického ORM.
2. Nastavenie Jdbi
Jdbi je usporiadané do jadra a niekoľkých voliteľných modulov.
Na začiatok musíme zahrnúť hlavný modul do našich závislostí:
org.jdbi jdbi3-jadro 3.1.0
V priebehu tohto článku si ukážeme príklady použitia databázy HSQL:
org.hsqldb hsqldb 2.4.0 test
Nájdeme najnovšiu verziu servera jdbi3-jadro, HSQLDB a ďalšie moduly Jdbi na serveri Maven Central.
3. Pripojenie k databáze
Najskôr sa musíme pripojiť k databáze. Aby sme to dosiahli, musíme určiť parametre pripojenia.
Východiskovým bodom je Jdbi trieda:
Jdbi jdbi = Jdbi.create ("jdbc: hsqldb: mem: testDB", "sa", "");
Tu špecifikujeme adresu URL pripojenia, používateľské meno a samozrejme heslo.
3.1. Ďalšie parametre
Ak potrebujeme uviesť ďalšie parametre, použijeme preťaženú metódu akceptujúcu a Vlastnosti objekt:
Vlastnosti vlastnosti = nové Vlastnosti (); properties.setProperty ("používateľské meno", "sa"); properties.setProperty ("heslo", ""); Jdbi jdbi = Jdbi.create ("jdbc: hsqldb: mem: testDB", vlastnosti);
V týchto príkladoch sme uložili Jdbi inštancia v lokálnej premennej. Je to preto, lebo ho použijeme na zasielanie výpisov a dotazov do databázy.
V skutočnosti iba volanie vytvoriť nenadväzuje nijaké spojenie s DB. Iba uloží parametre pripojenia na neskôr.
3.2. Pomocou a Dátový zdroj
Ak sa k databáze pripájame pomocou a Dátový zdroj, ako to zvyčajne býva, môžeme použiť príslušné vytvoriť preťaženie:
Jdbi jdbi = Jdbi.create (zdroj údajov);
3.3. Práca s rukoväťami
Skutočné pripojenia k databáze sú reprezentované inštanciami Rukoväť trieda.
Najjednoduchší spôsob, ako pracovať s rukoväťami a nechať ich automaticky zatvorené, je použitie výrazov lambda:
jdbi.useHandle (handle -> {doStuffWith (handle);});
Voláme useHandle keď nemusíme vracať hodnotu.
Inak používame sHandle:
jdbi.withHandle (handle -> {return computeValue (handle);});
Je tiež možné, aj keď sa to neodporúča, manuálne otvoriť rukoväť pripojenia; v takom prípade ho musíme uzavrieť, keď skončíme:
Jdbi jdbi = Jdbi.create ("jdbc: hsqldb: mem: testDB", "sa", ""); try (Handle handle = jdbi.open ()) {doStuffWith (handle); }
Našťastie, ako vidíme, Rukoväť náradie Uzatvárateľné, takže ho možno použiť so zdrojmi typu try-with-resources.
4. Jednoduché vyhlásenia
Teraz, keď vieme, ako získať pripojenie, sa pozrime, ako ho použiť.
V tejto časti vytvoríme jednoduchú tabuľku, ktorú použijeme v celom článku.
Na zasielanie výpisov ako napr vytvoriť tabuľku do databázy používame vykonať metóda:
handle.execute ("vytvoriť projekt tabuľky" + "(identita celého čísla, meno varchar (50), adresa URL varchar (100))");
vykonať vráti počet riadkov, ktoré boli ovplyvnené výpisom:
int updateCount = handle.execute ("vložiť do hodnôt projektu" + "(1, 'tutoriály', 'github.com/eugenp/tutorials')"); assertEquals (1, updateCount);
Vykonávanie je v skutočnosti iba pohodlná metóda.
Na zložitejšie prípady použitia sa pozrieme v ďalších častiach, ale predtým, ako to urobíme, sa musíme naučiť, ako extrahovať výsledky z databázy.
5. Dotazovanie na databázu
Najpriamočiarejším výrazom, ktorý vytvára výsledky z databázy, je dotaz SQL.
Aby sme mohli zadať dotaz pomocou Jdbi Handle, musíme minimálne:
- vytvorte dotaz
- zvoliť spôsob zastúpenia každého riadku
- iterovať nad výsledkami
Teraz sa pozrieme na každý z vyššie uvedených bodov.
5.1. Vytvorenie dopytu
Neprekvapujúco, Jdbi predstavuje dotazy ako inštancie súboru Dopyt trieda.
Jeden môžeme získať z držadla:
Query query = handle.createQuery ("select * from project");
5.2. Mapovanie výsledkov
Jdbi abstrahuje od JDBC Sada výsledkov, ktorý má dosť ťažkopádne API.
Preto ponúka niekoľko možností prístupu k stĺpcom, ktoré sú výsledkom dotazu alebo iného príkazu, ktorý vracia výsledok. Teraz uvidíme tie najjednoduchšie.
Každý riadok môžeme reprezentovať ako mapu:
query.mapToMap ();
Kľúčmi mapy budú vybrané názvy stĺpcov.
Alebo keď dotaz vráti jeden stĺpec, môžeme ho namapovať na požadovaný typ Java:
handle.createQuery ("vyberte názov z projektu"). mapTo (String.class);
Jdbi má zabudované mapovače pre mnoho bežných tried. Tie, ktoré sú špecifické pre niektorý knižničný alebo databázový systém, sú poskytované v samostatných moduloch.
Môžeme samozrejme tiež definovať a zaregistrovať našich mapovačov. Povieme si o tom v ďalšej časti.
Nakoniec môžeme riadky namapovať na fazuľu alebo inú vlastnú triedu. Pokročilé možnosti opäť uvidíme v vyhradenej sekcii.
5.3. Iterácia nad výsledkami
Keď sme sa rozhodli, ako mapovať výsledky volaním príslušnej metódy, dostávame a Výsledok objekt.
Potom ho môžeme použiť na iteráciu výsledkov po jednom riadku.
Tu sa pozrieme na najbežnejšie možnosti.
Výsledky môžeme iba zhromaždiť do zoznamu:
Zoznam
Alebo do iného Zbierka typ:
Zoznam výsledkov = query.mapTo (String.class) .collect (Collectors.toSet ());
Alebo môžeme výsledky iterovať ako prúd:
query.mapTo (String.class) .useStream ((stream stream) -> {doStuffWith (stream)});
Tu sme výslovne zadali znak Prúd premenná kvôli jasnosti, ale nie je to potrebné.
5.4. Získanie jedného výsledku
Ako špeciálny prípad, keď očakávame alebo sa zaujímame iba o jeden riadok, máme k dispozícii niekoľko vyhradených metód.
Ak chceme najviac jeden výsledok, môžeme použiť findFirst:
Voliteľné
Ako vidíme, vracia Voliteľné hodnota, ktorá je k dispozícii, iba ak dotaz vráti aspoň jeden výsledok.
Ak dotaz vráti viac ako jeden riadok, vráti sa iba prvý.
Ak namiesto toho chceme jeden jediný výsledok, používame findOnly:
Date onlyResult = query.mapTo (Date.class) .findOnly ();
Nakoniec, ak sú k dispozícii nulové výsledky alebo viac ako jeden, findOnly hodí IllegalStateException.
6. Parametre viazania
Často dotazy majú pevnú časť a parametrizovanú časť. To má niekoľko výhod, medzi ktoré patrí:
- bezpečnosť: zabránením zreťazenia reťazcov zabránime vloženiu SQL
- jednoduchosť: nemusíme si pamätať presnú syntax zložitých dátových typov, ako sú časové pečiatky
- výkon: statickú časť dopytu je možné analyzovať raz a uložiť do medzipamäte
Jdbi podporuje pozičné aj pomenované parametre.
Pozičné parametre vkladáme ako otázniky do dotazu alebo príkazu:
Dotaz positionalParamsQuery = handle.createQuery ("vyberte * z projektu, kde name =?");
Pomenované parametre namiesto toho začínajú dvojbodkou:
Dotaz namedParamsQuery = handle.createQuery ("vyberte * z projektu, kde adresa URL ako: vzor");
V obidvoch prípadoch na nastavenie hodnoty parametra použijeme jednu z variantov parametra viazať metóda:
positionalParamsQuery.bind (0, "návody"); namedParamsQuery.bind ("vzor", "% github.com / eugenp /%");
Upozorňujeme, že na rozdiel od JDBC, indexy začínajú na 0.
6.1. Viazanie viacerých pomenovaných parametrov naraz
Pomocou objektu môžeme tiež spojiť viac pomenovaných parametrov.
Povedzme, že máme tento jednoduchý dopyt:
Dotaz query = handle.createQuery ("vyberte ID z projektu, kde name =: name a url =: url"); Parametre mapy = nový HashMap (); params.put ("meno", "REST s pružinou"); params.put ("url", "github.com/eugenp/REST-With-Spring");
Potom môžeme napríklad použiť mapu:
query.bindMap (parametre);
Alebo môžeme objekt použiť rôznymi spôsobmi. Tu napríklad zviažeme objekt, ktorý sa riadi konvenciou JavaBean:
query.bindBean (paramsBean);
Mohli by sme však tiež viazať polia alebo metódy objektu; všetky podporované možnosti nájdete v dokumentácii Jdbi.
7. Vydávanie zložitejších výpisov
Teraz, keď sme videli dotazy, hodnoty a parametre, sa môžeme vrátiť k príkazom a použiť rovnaké vedomosti.
Pripomeňme, že vykonať metóda, ktorú sme videli predtým, je iba praktická skratka.
V skutočnosti, podobne ako pri dotazoch, Príkazy DDL a DML sú reprezentované ako inštancie triedy Aktualizácia.
Jeden môžeme získať zavolaním metódy createUpdate na rukoväti:
Aktualizácia update = handle.createUpdate ("VLOŽTE DO PROJEKTU (NÁZOV, URL) HODNOTY (: meno,: url)");
Potom na Aktualizácia máme všetky metódy viazania, ktoré máme v a Dopyt, takže časť 6. platí aj pre aktualizácie.url
Výpisy sa vykonávajú, keď voláme, prekvapujeme, vykonať:
int riadky = update.execute ();
Ako sme už videli, vráti počet ovplyvnených riadkov.
7.1. Extrakcia hodnôt stĺpca s automatickým prírastkom
Ako špeciálny prípad, keď máme príkaz vloženia s automaticky generovanými stĺpcami (zvyčajne automatický prírastok alebo sekvencie), možno budeme chcieť získať vygenerované hodnoty.
Potom nezavoláme vykonať, ale executeAndReturnGeneratedKeys:
Aktualizácia update = handle.createUpdate ("VLOŽTE DO PROJEKTU (NÁZOV, URL)" + "HODNOTY ('tutoriály', 'github.com/eugenp/tutorials')"); ResultBearing generatedKeys = update.executeAndReturnGeneratedKeys ();
ResultBearing je rovnaké rozhranie implementované Dopyt trieda ktoré sme už videli predtým, takže už vieme, ako ich používať:
generatedKeys.mapToMap () .findOnly (). get ("id");
8. Transakcie
Transakciu potrebujeme vždy, keď musíme vykonať viac príkazov ako jednu atómovú operáciu.
Rovnako ako v prípade úchytov na pripojenie, aj v tomto prípade zavádzame transakciu volaním metódy s uzáverom:
handle.useTransaction ((Handle h) -> {haveFunWith (h);});
Rovnako ako v prípade rukovätí sa transakcia automaticky uzavrie, keď sa uzávierka vráti.
Musíme však transakciu potvrdiť alebo vrátiť späť pred návratom:
handle.useTransaction ((Handle h) -> {h.execute ("..."); h.commit ();});
Ak je však z uzávierky vyvolaná výnimka, Jdbi transakciu automaticky vráti späť.
Rovnako ako u rukovätí, aj tu máme vyhradenú metódu, inTransaction, ak chceme niečo vrátiť z uzávierky:
handle.inTransaction ((Handle h) -> {h.execute ("..."); h.commit (); return true;});
8.1. Manuálna správa transakcií
Aj keď sa to vo všeobecnosti neodporúča, môžeme tiež začať a Zavrieť transakcia manuálne:
handle.begin (); // ... handle.commit (); handle.close ();
9. Závery a ďalšie čítanie
V tomto tutoriáli sme predstavili jadro Jdbi: dotazy, výpisy a transakcie.
Vynechali sme niektoré pokročilé funkcie, ako je vlastné mapovanie riadkov a stĺpcov a dávkové spracovanie.
Nerozprávali sme sa ani o žiadnom z voliteľných modulov, najmä o rozšírení objektu SQL.
Všetko je podrobne predstavené v dokumentácii Jdbi.
Implementáciu všetkých týchto príkladov a útržkov kódu nájdete v projekte GitHub - jedná sa o projekt Maven, takže by malo byť ľahké ho importovať a spustiť tak, ako je.