Sprievodca obalovým programom JDBC sql2o

1. Úvod

V tomto výučbe sa pozrieme na Sql2o, malú a rýchlu knižnicu pre prístup relačnej databázy v idiomatickej Jave.

Za zmienku stojí, že aj keď Sql2o pracuje tak, že mapuje výsledky dotazu na POJO (obyčajné staré objekty Java), nie je to úplné riešenie ORM, ako napríklad Hibernate.

2. Nastavenie Sql2o

Sql2o je jediný súbor jar, ktorý môžeme ľahko pridať do závislostí nášho projektu:

 org.sql2o sql2o 1.6.0 

V našich príkladoch použijeme aj zabudovanú databázu HSQL; aby sme mohli nasledovať, môžeme ho zahrnúť tiež:

 org.hsqldb hsqldb 2.4.0 test 

Maven Central hostí najnovšiu verziu servera sql2o a HSQLDB.

3. Pripojenie k databáze

Na vytvorenie spojenia vychádzame z inštancie Sql2o trieda:

Sql2o sql2o = nový Sql2o ("jdbc: hsqldb: mem: testDB", "sa", "");

Tu špecifikujeme adresu URL pripojenia, používateľské meno a heslo ako parametre konštruktora.

The Sql2o objekt je bezpečný pre vlákna a môžeme ho zdieľať v celej aplikácii.

3.1. Pomocou a Dátový zdroj

Vo väčšine aplikácií budeme chcieť použiť a Dátový zdrojnamiesto surového DriverManager pripojenie, napríklad na využitie spoločného fondu pripojení alebo na určenie ďalších parametrov pripojenia. Nebojte sa, Sql2o nás kryje:

Sql2o sql2o = nový Sql2o (zdroj údajov);

3.2. Práca s pripojeniami

Iba inštancia a Sql2o objekt nenadväzuje žiadne pripojenie k databáze.

Namiesto toho používame otvorené metóda na získanie a Pripojenie objekt (všimnite si, že nejde o JDBC Pripojenie). Odkedy Pripojenie je Automatické uzatváranie, môžeme to zabaliť do bloku try-with-resources:

try (Connection connection = sql2o.open ()) {// use the connection}

4. Vkladanie a aktualizácia výpisov

Poďme teraz vytvoriť databázu a vložiť do nej nejaké údaje. V celom výučbe budeme používať jednoduchú tabuľku s názvom projekt:

connection.createQuery ("create table project" + "(id integer identity, name varchar (50), url varchar (100))"). executeUpdate ();

executeUpdate vracia Pripojenie objekt, aby sme mohli reťaziť viac hovorov. Potom, ak chceme vedieť počet ovplyvnených riadkov, použijeme getResult:

assertEquals (0, connection.getResult ());

Použijeme vzor, ​​ktorý sme práve videli - createQuery a executeUpdate -pre všetky výpisy DDL, INSERT a UPDATE.

4.1. Získanie vygenerovaných kľúčových hodnôt

V niektorých prípadoch však možno budeme chcieť získať vygenerované kľúčové hodnoty späť. Toto sú hodnoty kľúčových stĺpcov, ktoré sa počítajú automaticky (ako pri použití automatického prírastku v určitých databázach).

Robíme to v dvoch krokoch. Najprv s ďalším parametrom do createQuery:

Dotaz na dotaz = connection.createQuery ("vložiť do projektu (názov, adresa URL)" + "hodnoty ('tutoriály', 'github.com/eugenp/tutorials')", pravda);

Potom s odvolaním sa getKey o pripojení:

assertEquals (0, query.executeUpdate (). getKey ());

Ak je klávesov viac ako jeden, použijeme ich getKeys namiesto toho vráti pole:

assertEquals (1, query.executeUpdate (). getKeys () [0]);

5. Extrakcia údajov z databázy

Poďme teraz k jadru veci: VYBERTE dotazy a mapovanie množín výsledkov na objekty Java.

Najprv musíme definovať triedu POJO s getrami a setrami, ktoré budú reprezentovať našu tabuľku projektov:

public class Project {long id; súkromné ​​meno reťazca; súkromná reťazcová adresa URL; // Štandardné getre a setre}

Potom, rovnako ako predtým, napíšeme náš dopyt:

Query query = connection.createQuery ("select * from project order by id");

Tentokrát však použijeme novú metódu, executeAndFetch:

Zoznam zoznam = query.executeAndFetch (Project.class);

Ako vidíme, metóda berie triedu výsledkov ako parameter, do ktorého Sql2o namapuje riadky surovej výsledkovej sady pochádzajúce z databázy.

5.1. Mapovanie stĺpcov

SQL2O mapuje stĺpce na vlastnosti JavaBean podľa názvu, nerozlišujú sa veľké a malé písmená.

Konvencie pomenovania sa však medzi Java a relačnými databázami líšia. Predpokladajme, že do svojich projektov pridáme vlastnosť dátumu vytvorenia:

public class Project {long id; súkromné ​​meno reťazca; súkromná reťazcová adresa URL; súkromné ​​Dátum vytvoreniaDátum; // Štandardné getre a setre}

V schéme databázy s najväčšou pravdepodobnosťou zavoláme tú istú vlastnosť dátum vytvorenia.

Môžeme to samozrejme pomenovať aj v našich dotazoch:

Query query = connection.createQuery ("vyberte názov, adresu URL, dátum vytvorenia ako dátum vytvorenia z projektu");

Je to však zdĺhavé a strácame možnosť používať vyberte *.

Ďalšou možnosťou je dať pokyn aplikácii Sql2o na mapovanie dátum vytvorenia do dátum vytvorenia. To znamená, že môžeme povedať dopyt o mapovaní:

connection.createQuery ("select * from project") .addColumnMapping ("creation_date", "creationDate");

To je pekné, ak použijeme dátum vytvorenia striedmo, v niekoľkých otázkach; pri rozsiahlom použití vo väčšom projekte je však únavné a náchylné na chyby rozprávať stále tie isté skutočnosti.

Našťastie môžeme globálne určiť mapovania:

Mapové mapovania = nový HashMap (); mappings.put ("CREATION_DATE", "creationDate"); sql2o.setDefaultColumnMappings (mapovania);

To samozrejme spôsobí všetky prípady dátum vytvorenia na ktoré sa má namapovať dátum vytvorenia, takže to je ďalší dôvod pre snahu o to, aby boli názvy v definíciách našich údajov konzistentné.

5.2. Skalárne výsledky

Niekedy chceme z dotazu extrahovať jeden skalárny výsledok. Napríklad keď potrebujeme spočítať počet záznamov.

V tých prípadoch je definovanie triedy a opakovanie zoznamu, o ktorom vieme, že obsahuje jeden prvok, prehnané. Teda Sql2o zahŕňa executeScalar metóda:

Query query = connection.createQuery ("select count (*) from project"); assertEquals (2, query.executeScalar (Integer.class));

Tu špecifikujeme návratový typ, ktorý má byť Celé číslo. To je však voliteľné a môžeme nechať rozhodnúť, aký bude podkladový ovládač JDBC.

5.3. Komplexné výsledky

Niekedy sa nemusí zložité dotazy (napríklad na vytváranie prehľadov) ľahko namapovať na objekt Java. Mohli by sme sa tiež rozhodnúť, že nechceme kódovať triedu Java tak, aby sa používala iba v jednom dotaze.

Teda Sql2o tiež umožňuje dynamické mapovanie na nižšej úrovni na tabuľkové dátové štruktúry. Získame k tomu prístup pomocou executeAndFetchTable metóda:

Query query = connection.createQuery ("select * from project order by id"); Tabuľková tabuľka = query.executeAndFetchTable ();

Potom môžeme extrahovať zoznam máp:

Zoznam list = table.asList (); assertEquals ("návody", list.get (0) .get ("meno"));

Alternatívne môžeme údaje namapovať na zoznam Riadok objekty, ktoré sú mapovaniami od názvov stĺpcov k hodnotám podobným Sada výsledkovs:

Zoznam riadkov = table.rows (); assertEquals ("tutoriály", rows.get (0) .getString ("meno"));

6. Záväzné parametre dotazu

Mnoho dotazov SQL má pevnú štruktúru s niekoľkými parametrizovanými časťami. Tieto čiastočne dynamické dotazy by sme mohli naivne písať so zreťazením reťazcov.

Sql2o však umožňuje parametrizované dotazy, takže:

  • Vyhýbame sa útokom SQL injection
  • Umožňujeme databáze ukladať do pamäte cache často používané dotazy a zvyšovať výkon
  • Nakoniec sme ušetrení od potreby kódovať zložité typy, ako sú dátumy a časy

Takže môžeme použiť pomenované parametre so Sql2o, aby sme dosiahli všetky vyššie uvedené. Parametre zavedieme dvojbodkou a spojíme ich s addParameter metóda:

Dotaz na dotaz = connection.createQuery ("vložiť do projektu (name, url) hodnoty (: name,: url)") .addParameter ("name", "REST s jarou") .addParameter ("url", "github.com / eugenp / REST-With-Spring "); assertEquals (1, query.executeUpdate (). getResult ());

6.1. Viazanie z POJO

Sql2o ponúka alternatívny spôsob viazania parametrov: to znamená pomocou POJO ako zdroj. Táto technika je obzvlášť vhodná, keď má dopyt veľa parametrov a všetky odkazujú na rovnakú entitu. Poďme sa teda predstaviť the viazať metóda:

Projekt projektu = nový projekt (); project.setName („REST with Spring“); project.setUrl ("github.com/eugenp/REST-With-Spring"); connection.createQuery ("vložiť do hodnoty projektu (názov, adresa URL) (: názov,: adresa URL)") .bind (projekt) .executeUpdate (); assertEquals (1, connection.getResult ());

7. Transakcie a dávkové dotazy

Pomocou transakcie môžeme vydať viac príkazov SQL ako jednu operáciu, ktorá je atómová. To znamená, že buď uspeje, alebo zlyhá hromadne bez priebežných výsledkov. Transakcie sú v skutočnosti jednou z kľúčových vlastností relačných databáz.

Na otvorenie transakcie používame beginTransaction metóda namiesto otvorené metóda, ktorú sme doteraz používali:

vyskúšajte (Connection connection = sql2o.beginTransaction ()) {// tu je transakcia aktívna}

Keď poprava opustí blok, Sql2o automaticky vráti transakciu späť ak je stále aktívny.

7.1. Ručné potvrdenie a vrátenie

Avšak môžeme transakciu výslovne potvrdiť alebo vrátiť späť pomocou vhodných metód:

try (Connection connection = sql2o.beginTransaction ()) {boolean transactionSuccessful = false; // vykonať nejaké operácie if (transactionSuccessful) {connection.commit (); } else {connection.rollback (); }}

Poznač si to oboje spáchať a rollback ukončiť transakciu. Následné príkazy budú bežať bez transakcie, takže sa na konci bloku nebudú automaticky vracať späť.

Transakciu však môžeme zaviazať alebo vrátiť späť bez jej ukončenia:

try (Connection connection = sql2o.beginTransaction ()) {List list = connection.createQuery ("select * from project") .executeAndFetchTable () .asList (); assertEquals (0, list.size ()); // vložiť alebo aktualizovať nejaké dátové pripojenie.rollback (false); // vykonanie ďalších dotazov na vloženie alebo aktualizáciu} // implicitné vrátenie späť try (Connection connection = sql2o.beginTransaction ()) {List list = connection.createQuery ("select * from project") .executeAndFetchTable () .asList (); assertEquals (0, list.size ()); }

7.2. Dávkové operácie

Keď potrebujeme vydať to isté vyhlásenie mnohokrát s rôznymi parametrami, ich hromadné spustenie poskytuje veľkú výkonnostnú výhodu.

Kombinácia dvoch z techník, ktoré sme doteraz opísali - parametrizované dotazy a transakcie - je našťastie dosť ľahké spustiť ich hromadne:

  • Najskôr dotaz vytvoríme iba raz
  • Potom zviažeme parametre a zavoláme addToBatch pre každú inštanciu dotazu
  • Nakoniec zavoláme executeBatch:
try (Connection connection = sql2o.beginTransaction ()) {Query query = connection.createQuery ("insert into project (name, url)" + "values ​​(: name,: url)"); for (int i = 0; i <1000; i ++) {query.addParameter ("name", "tutorials" + i); query.addParameter ("url", "//github.com/eugenp/tutorials" + i); query.addToBatch (); } query.executeBatch (); connection.commit (); } try (Connection connection = sql2o.beginTransaction ()) {assertEquals (1000L, connection.createQuery ("select count (*) from project"). executeScalar ()); }

7.3. Lazy Fetch

Naopak, keď jeden dopyt vráti veľké množstvo výsledkov, ich konverzia a uloženie do zoznamu je náročné na pamäť.

Takže Sql2o podporuje lenivý režim, v ktorom sú riadky vrátené a mapované po jednom:

Query query = connection.createQuery ("select * from project"); try (ResultSetIterable projects = query.executeAndFetchLazy (Project.class)) {for (Project p: projects) {// niečo s projektom vykonajte}}

Poznač si to ResultSetIterable je Automatické uzatváranie a je určený na použitie s vyskúšajte zdroje uzavrieť podkladové Sada výsledkov po dokončení.

8. Závery

V tomto tutoriáli sme predstavili prehľad knižnice Sql2o a jej najbežnejších vzorov používania. Ďalšie informácie nájdete vo wiki Sql20 na GitHub.

Implementáciu všetkých týchto príkladov a útržkov kódu nájdete tiež v projekte GitHub, ktorý je projektom Maven, takže by malo byť ľahké ho importovať a bežať tak, ako je.


$config[zx-auto] not found$config[zx-overlay] not found