JDBC s Groovy

1. Úvod

V tomto článku sa pozrieme na to, ako dotazovať relačné databázy s JDBC pomocou idiomatického Groovy.

JDBC, hoci je relatívne nízkej úrovne, je základom väčšiny ORM a iných knižníc na vysokej úrovni pre prístup k údajom v JVM. A môžeme samozrejme použiť JDBC priamo v Groovy; má však dosť ťažkopádne API.

Našťastie pre nás, štandardná knižnica Groovy stavia na JDBC a predstavuje rozhranie, ktoré je čisté, jednoduché a výkonné. Budeme teda skúmať modul Groovy SQL.

Ideme sa pozrieť na JDBC v obyčajnom Groovy, neberieme do úvahy žiadny rámec ako Spring, pre ktorý máme ďalších sprievodcov.

2. Nastavenie JDBC a Groovy

Musíme zahrnúť groovy-modul sql medzi našimi závislosťami:

 org.codehaus.groovy groovy 2.4.13 org.codehaus.groovy groovy-sql 2.4.13 

Ak používame groovy-all, nie je potrebné ho výslovne uvádzať:

 org.codehaus.groovy groovy-all 2.4.13 

Nájdeme najnovšiu verziu servera groovy, groovy-sql a groovy-všetko na Maven Central.

3. Pripojenie k databáze

Prvá vec, ktorú musíme urobiť, aby sme mohli pracovať s databázou, je pripojenie sa k nej.

Poďme si predstaviť groovy.sql.Sql triedy, ktorú použijeme na všetky operácie v databáze s modulom Groovy SQL.

Prípad z Sql predstavuje databázu, na ktorej chceme pracovať.

Avšak inštancia Sqlnie je jediné pripojenie k databáze. O spojeniach si povieme neskôr, teraz si s nimi nerobme starosti. predpokladajme, že všetko čarovne funguje.

3.1. Zadanie parametrov pripojenia

V tomto článku budeme používať databázu HSQL, čo je ľahká relačná DB, ktorá sa väčšinou používa pri testoch.

Pripojenie k databáze vyžaduje adresu URL, ovládač a prístupové poverenia:

Mapa dbConnParams = [url: 'jdbc: hsqldb: mem: testDB', užívateľ: 'sa', heslo: '', ovládač: 'org.hsqldb.jdbc.JDBCDriver']

Tu sme sa rozhodli špecifikovať tie, ktoré používajú a Mapa, aj keď to nie je jediná možná voľba.

Potom môžeme získať spojenie od spoločnosti Sql trieda:

def sql = Sql.newInstance (dbConnParams)

Uvidíme, ako sa to bude používať v nasledujúcich častiach.

Keď skončíme, mali by sme vždy uvoľniť všetky súvisiace zdroje:

sql.close ()

3.2. Pomocou a Dátový zdroj

Je bežné, najmä v programoch bežiacich na aplikačnom serveri, použiť na pripojenie k databáze zdroj údajov.

Tiež, keď chceme združiť spojenia alebo použiť JNDI, je zdroj údajov najprirodzenejšou možnosťou.

Groovy Sql trieda akceptuje zdroje dát v pohode:

def sql = Sql.newInstance (zdroj údajov)

3.3. Automatická správa zdrojov

Nezabudnem zavolať Zavrieť() keď skončíme s Sql príklad je zdĺhavý; stroje si koniec koncov pamätajú veci oveľa lepšie ako my.

S Sql môžeme zabaliť náš kód do uzávierky a nechať zavolať Groovy Zavrieť() automaticky, keď to ovládací prvok opustí, a to aj v prípade výnimiek:

Sql.withInstance (dbConnParams) {sql sql -> haveFunWith (sql)}

4. Vydávanie výkazov proti databáze

Teraz môžeme pokračovať k zaujímavým veciam.

Najjednoduchším a nešpecializovaným spôsobom, ako vydať vyhlásenie proti databáze, je vykonať metóda:

sql.execute "vytvoriť tabuľku PROJECT (id integer not null, name varchar (50), url varchar (100))"

Teoreticky to funguje ako pre príkazy DDL / DML, tak aj pre dotazy; jednoduchý formulár vyššie však neponúka spôsob, ako získať späť výsledky dotazov. Dotazy si necháme na neskôr.

The vykonať metóda má niekoľko preťažených verzií, ale opäť sa pozrieme na pokročilejšie prípady použitia tejto a ďalších metód v ďalších častiach.

4.1. Vkladanie údajov

Pre vkladanie údajov v malom množstve a v jednoduchých scenároch, vykonať predtým diskutovaná metóda je úplne v poriadku.

Pre prípady, keď sme vygenerovali stĺpce (napr. So sekvenciami alebo automatickým prírastkom) a chceme poznať vygenerované hodnoty, existuje vyhradená metóda: executeInsert.

Ako pre vykonať, teraz sa pozrieme na najjednoduchšie dostupné preťaženie metód a zložitejšie varianty necháme na ďalšiu časť.

Predpokladajme teda, že máme tabuľku s primárnym kľúčom s automatickým prírastkom (identita v jazyku HSQLDB):

sql.execute "vytvoriť tabuľku PROJEKT (ID IDENTITY, NÁZOV VARCHAR (50), URL VARCHAR (100))"

Vložme riadok do tabuľky a výsledok uložme do premennej:

def ids = sql.executeInsert "" "VLOŽTE DO PROJEKTU (NÁZOV, URL) HODNOTY ('tutoriály', 'github.com/eugenp/tutorials')" ""

executeInsert správa sa presne ako vykonať, ale čo sa vracia?

Ukazuje sa, že návratovou hodnotou je matica: jej riadky sú vložené riadky (nezabudnite, že jeden príkaz môže spôsobiť vloženie viacerých riadkov) a jeho stĺpce sú vygenerované hodnoty.

Znie to komplikovane, ale v našom prípade, ktorý je zďaleka najbežnejším, je jeden riadok a jedna vygenerovaná hodnota:

assertEquals (0, ids [0] [0])

Následné vloženie vráti vygenerovanú hodnotu 1:

ids = sql.executeInsert "" "VLOŽTE DO HODNOTY PROJEKTU (NÁZOV, URL) ('REST with Spring', 'github.com/eugenp/REST-With-Spring')" "" assertEquals (1, ids [0] [ 0])

4.2. Aktualizácia a mazanie údajov

Podobne existuje vyhradená metóda na úpravu a mazanie údajov: executeUpdate.

Toto sa opäť líši od vykonať iba v jeho návratovej hodnote a my sa pozrieme iba na jeho najjednoduchšiu formu.

Návratová hodnota je v tomto prípade celé číslo, počet ovplyvnených riadkov:

def count = sql.executeUpdate ("UPDATE PROJECT SET URL = '//' + URL") assertEquals (2, count)

5. Dotazovanie na databázu

Keď sa pýtame do databázy, veci sa začnú zhoršovať.

Zaoberanie sa JDBC Sada výsledkov trieda nie je práve zábava. Našťastie pre nás, Groovy ponúka všetko pekné.

5.1. Iterácia nad výsledkami dotazu

Zatiaľ čo slučky majú taký starý štýl ... dnes sme všetci v uzavretí.

A Groovy je tu, aby vyhovoval nášmu vkusu:

sql.eachRow ("VYBERTE * Z PROJEKTU") {GroovyResultSet rs -> haveFunWith (rs)}

The eachRow metóda vydá náš dopyt proti databáze a zavolá uzávierku nad každým riadkom.

Ako vidíme, riadok je reprezentovaný inštanciou Sada GroovyResultSet, čo je rozšírenie obyčajného starého Sada výsledkov s niekoľkými pridanými dobrotami. Čítajte ďalej a dozviete sa o ňom viac.

5.2. Prístup k súpravám výsledkov

Okrem všetkých Sada výsledkov metódy, Sada GroovyResultSet ponúka niekoľko pohodlných nástrojov.

Hlavne vystavuje pomenované vlastnosti zodpovedajúce názvom stĺpcov:

sql.eachRow ("SELECT * FROM PROJECT") {rs -> assertNotNull (rs.name) assertNotNull (rs.URL)}

Všimnite si, ako sa v názvoch vlastností nerozlišujú malé a veľké písmená.

Sada GroovyResultSet tiež ponúka prístup k stĺpcom pomocou nulového indexu:

sql.eachRow ("VÝBOR * Z PROJEKTU") {rs -> assertNotNull (rs [0]) assertNotNull (rs [1]) assertNotNull (rs [2])}

5.3. Stránkovanie

Výsledky môžeme ľahko zobraziť na stránke, t. J. Načítať iba podmnožinu začínajúcu od určitého posunu až po maximálny počet riadkov. To je bežný problém napríklad v prípade webových aplikácií.

eachRow a súvisiace metódy majú preťaženia akceptujúce posun a maximálny počet vrátených riadkov:

def offset = 1 def maxResults = 1 def riadky = sql.rows ('SELECT * FROM PROJECT ORDER BY NAME', offset, maxResults) assertEquals (1, rows.size ()) assertEquals ('REST with Spring', riadky [0 ].názov)

Tu je riadkov metóda vráti zoznam riadkov namiesto opakovania podobných rád eachRow.

6. Parametrizované dotazy a vyhlásenia

Častejšie nie sú dotazy a vyhlásenia v čase kompilácie úplne opravené; majú zvyčajne statickú časť a dynamickú časť vo forme parametrov.

Ak uvažujete o zreťazení reťazcov, zastavte sa a pokračujte v čítaní o SQL Injection!

Už sme spomenuli, že metódy, ktoré sme videli v predchádzajúcich častiach, majú veľa preťažení pre rôzne scenáre.

Poďme predstaviť tie preťaženia, ktoré sa zaoberajú parametrami v dotazoch a príkazoch SQL.

6.1. Struny so zástupnými symbolmi

V štýle podobnom obyčajnému JDBC môžeme použiť pozičné parametre:

sql.execute ('INSERT INTO PROJECT (NAME, URL) VALUES (?,?)', 'tutorials', 'github.com/eugenp/tutorials')

alebo môžeme použiť pomenované parametre s mapou:

sql.execute ('INSERT INTO PROJECT (NAME, URL) VALUES (: name,: url)', [name: 'REST with Spring', url: 'github.com/eugenp/REST-With-Spring'])

Toto funguje pre vykonať, executeUpdate, riadkov a eachRow. executeInsert podporuje aj parametre, ale jeho podpis je trochu iný a zložitejší.

6.2. Groovy struny

Môžeme sa tiež rozhodnúť pre štýl Groovier pomocou GStringov so zástupnými symbolmi.

Všetky metódy, ktoré sme videli, nenahrádzajú zástupné symboly v reťazcoch GS obvyklým spôsobom; skôr ich vkladajú ako parametre JDBC, čím zabezpečujú správne zachovanie syntaxe SQL, bez nutnosti nič citovať alebo uniknúť, a teda ani riziko vstrekovania.

To je úplne v poriadku, bezpečné a Groovy:

def name = 'REST with Spring' def url = 'github.com/eugenp/REST-With-Spring' sql.execute "VLOŽTE DO PROJEKTU (NÁZOV, URL) HODNOTY ($ {name}, $ {url})"

7. Transakcie a spojenia

Zatiaľ sme preskočili veľmi dôležitú obavu: transakcie.

V skutočnosti sme vôbec nehovorili o tom, ako sa majú Groovy Sql spravuje spojenia.

7.1. Krátkodobé spojenia

V doteraz predložených príkladoch každý dotaz alebo príkaz bol odoslaný do databázy pomocou nového vyhradeného pripojenia. Sql ukončí spojenie, akonáhle sa operácia ukončí.

Samozrejme, ak používame skupinu pripojení, vplyv na výkon môže byť malý.

Napriek tomu ak chceme vydať viac príkazov a dotazov DML ako jednu atómovú operáciu, potrebujeme transakciu.

Aby bola transakcia v prvom rade možná, potrebujeme spojenie, ktoré sa rozprestiera na viacerých príkazoch a dotazoch.

7.2. Transakcie s pripojením v medzipamäti

Groovy SQL nám neumožňuje explicitne vytvárať alebo pristupovať k transakciám.

Namiesto toho používame s transakciou metóda s uzáverom:

sql.withTransaction {sql.execute "" "VLOŽTE DO PROJEKTU (NÁZOV, URL) HODNOTY ('tutoriály', 'github.com/eugenp/tutorials')" "" sql.execute "" "VLOŽTE DO PROJEKTU (NÁZOV, URL ) HODNOTY ('REST with Spring', 'github.com/eugenp/REST-With-Spring') "" "}

Vo vnútri uzávierky sa pre všetky dotazy a príkazy používa jediné databázové pripojenie.

Transakcia sa ďalej automaticky vykoná po ukončení uzávierky, pokiaľ nedôjde k jej predčasnému ukončeniu z dôvodu výnimky.

Aktuálnu transakciu však môžeme potvrdiť alebo vrátiť späť aj metódami v Sql trieda:

sql.withTransaction {sql.execute "" "VLOŽTE DO PROJEKTU (NÁZOV, URL) HODNOTY ('tutoriály', 'github.com/eugenp/tutorials')" "" sql.commit () sql.execute "" "VLOŽTE DO HODNOTY PROJEKTU (NÁZOV, URL) ('REST with Spring', 'github.com/eugenp/REST-With-Spring') "" "sql.rollback ()}

7.3. Spojenia v medzipamäti bez transakcie

Nakoniec znova použijeme databázové pripojenie bez vyššie opísanej sémantiky transakcií cacheConnection:

sql.cacheConnection {sql.execute "" "VLOŽTE DO PROJEKTU (NÁZOV, URL) HODNOTY ('tutoriály', 'github.com/eugenp/tutorials')" "" hodiť novú Výnimku ('This does not roll back')}

8. Závery a ďalšie čítanie

V tomto článku sme sa pozreli na modul Groovy SQL a na to, ako vylepšuje a zjednodušuje JDBC pomocou uzáverov a reťazcov Groovy.

Potom môžeme bezpečne dospieť k záveru, že obyčajný starý JDBC vyzerá trochu modernejšie s posypom Groovy!

Nehovorili sme o každej jednej funkcii Groovy SQL; napríklad sme vynechali dávkové spracovanie, uložené procedúry, metadáta a ďalšie veci.

Ďalšie informácie nájdete v dokumentácii k Groovy.

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.


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