JDBC s Groovyem

1. Uvod

U ovom ćemo članku pogledati kako postaviti upit za relacijske baze podataka s JDBC, koristeći idiomatski Groovy.

JDBC, iako je relativno nizak, temelj je većine ORM-ova i ostalih knjižnica za pristup podacima na visokoj razini na JVM-u. A JDBC možemo koristiti izravno u Groovyju, naravno; međutim, ima prilično glomazan API.

Na našu sreću, standardna knjižnica Groovy nadovezuje se na JDBC kako bi predstavila sučelje čisto, jednostavno, ali moćno. Dakle, istražit ćemo Groovy SQL modul.

Pogledat ćemo JDBC u običnom Groovyu, ne uzimajući u obzir bilo kakav okvir kao što je Spring, za koji imamo druge vodiče.

2. JDBC i Groovy postavljanje

Moramo uključiti groovy-sql modul među našim ovisnostima:

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

Nije potrebno izričito ga navoditi ako koristimo groovy-all:

 org.codehaus.groovy groovy-sve 2.4.13 

Možemo pronaći najnoviju verziju groovy, groovy-sql i groovy-all na Maven Central.

3. Povezivanje s bazom podataka

Prvo što moramo učiniti da bismo radili s bazom podataka je povezivanje s njom.

Uvedimo groovy.sql.Sql klase, koju ćemo koristiti za sve operacije na bazi podataka s Groovy SQL modulom.

Primjer Sql predstavlja bazu podataka na kojoj želimo raditi.

Međutim, primjerak Sqlnije jedna veza baze podataka. O vezama ćemo kasnije, ne brinimo sada o njima; pretpostavimo samo da sve čarobno djeluje.

3.1. Određivanje parametara veze

Kroz ovaj ćemo članak koristiti HSQL bazu podataka, koja je lagani relacijski DB koji se uglavnom koristi u testovima.

Veza baze podataka treba URL, upravljački program i vjerodajnice za pristup:

Mapa dbConnParams = [url: 'jdbc: hsqldb: mem: testDB', user: 'sa', password: '', driver: 'org.hsqldb.jdbc.JDBCDriver']

Ovdje smo odlučili navesti one koji koriste Karta, iako to nije jedini mogući izbor.

Tada možemo dobiti vezu od Sql razred:

def sql = Sql.newInstance (dbConnParams)

Vidjet ćemo kako će se koristiti u sljedećim odjeljcima.

Kad završimo, uvijek bismo trebali objaviti sve povezane resurse:

sql.close ()

3.2. Korištenje a Izvor podataka

Uobičajeno je, posebno u programima koji se izvode unutar aplikacijskog poslužitelja, korištenje izvora podataka za povezivanje s bazom podataka.

Također, kada želimo spojiti veze ili koristiti JNDI, izvor podataka je najprirodnija opcija.

Groovyjeva Sql klasa izvrsno prihvaća izvore podataka:

def sql = Sql.newInstance (izvor podataka)

3.3. Automatsko upravljanje resursima

Sjetivši se nazvati Zatvoriti() kad završimo s Sql instanca je zamorna; strojevi uostalom pamte stvari puno bolje nego mi.

S Sql možemo umotati naš kod u zatvaranje i nazvati Groovy Zatvoriti() automatski kada ga kontrola napusti, čak i u slučaju iznimaka:

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

4. Izdavanje izjava protiv baze podataka

Sad možemo prijeći na zanimljive stvari.

Najjednostavniji i nespecijalizirani način izdavanja izjave protiv baze podataka je izvršiti metoda:

sql.execute "izradi tablicu PROJECT (id integer nije null, ime varchar (50), url varchar (100))"

U teoriji radi i za DDL / DML izjave i za upite; međutim, jednostavni obrazac gore ne nudi način za vraćanje rezultata upita. Upite ćemo ostaviti za kasnije.

The izvršiti metoda ima nekoliko preopterećenih verzija, ali opet ćemo u sljedećim odjeljcima pogledati naprednije slučajeve korištenja ove i drugih metoda.

4.1. Umetanje podataka

Za umetanje podataka u malim količinama i u jednostavnim scenarijima, izvršiti prethodno raspravljena metoda je sasvim u redu.

Međutim, za slučajeve kada smo generirali stupce (npr. Sa sekvencama ili automatskim povećanjem) i želimo znati generirane vrijednosti, postoji namjenska metoda: executeInsert.

Što se tiče izvršiti, sada ćemo pogledati najjednostavniju dostupnu metodu preopterećenja, ostavljajući složenije varijante za kasniji odjeljak.

Dakle, pretpostavimo da imamo tablicu s primarnim ključem sa automatskim povećanjem (identitet u jeziku HSQLDB):

sql.execute "izradi tablicu PROJEKT (ID IDENTITETA, IME VARCHAR (50), URL VARCHAR (100))"

Umetnimo red u tablicu i spremimo rezultat u varijablu:

def ids = sql.executeInsert "" "INSERT IN TO PROJECT (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')" ""

executeInsert ponaša se točno kao izvršiti, ali što se vraća?

Ispada da je povratna vrijednost matrica: njezini su retci umetnuti retci (ne zaboravite da jedan izraz može dovesti do umetanja više redaka), a stupci su generirane vrijednosti.

Zvuči komplicirano, ali u našem slučaju, koji je daleko najčešći, postoji jedan redak i jedna generirana vrijednost:

assertEquals (0, id [0] [0])

Sljedeće umetanje vratilo bi generiranu vrijednost 1:

ids = sql.executeInsert "" "INSERT IN TO PROJECT (NAME, URL) VALUES ('REST with Spring', 'github.com/eugenp/REST-With-Spring')" "" assertEquals (1, ids [0] [ 0])

4.2. Ažuriranje i brisanje podataka

Slično tome, postoji posebna metoda za izmjenu i brisanje podataka: executeUpdate.

Opet se ovo razlikuje od izvršiti samo u njegovoj povratnoj vrijednosti, a mi ćemo pogledati samo njegov najjednostavniji oblik.

Povratna vrijednost, u ovom slučaju, je cijeli broj, broj zahvaćenih redaka:

def count = sql.executeUpdate ("AŽURIRANJE POSTAVKE PROJEKTA URL = '//' + URL") assertEquals (2, count)

5. Upit o bazi podataka

Stvari počinju dobivati ​​Groovy kad upitamo bazu podataka.

Suočavanje s JDBC-om Postavi rezultat razred nije baš zabavan. Srećom po nas, Groovy nudi lijepu apstrakciju nad svim tim.

5.1. Iteriranje rezultata pretraživanja

Iako su petlje tako stari stil ... danas smo svi u zatvaranju.

A Groovy je tu da odgovara našem ukusu:

sql.eachRow ("SELECT * FROM PROJECT") {GroovyResultSet rs -> haveFunWith (rs)}

The svakiRed metoda izdaje naš upit prema bazi podataka i poziva zatvaranje svakog retka.

Kao što vidimo, red je predstavljen primjerom GroovyResultSet, što je produžetak običnog starog Postavi rezultat s nekoliko dodanih dobrota. Pročitajte kako biste saznali više o tome.

5.2. Pristup skupovima rezultata

Pored svih Postavi rezultat metode, GroovyResultSet nudi nekoliko prikladnih uslužnih programa.

Uglavnom izlaže imenovana svojstva koja se podudaraju s imenima stupaca:

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

Imajte na umu kako imena svojstava ne razlikuju velika i mala slova.

GroovyResultSet također nudi pristup stupcima koji koriste indeks zasnovan na nuli:

sql.eachRow ("SELECT * FROM PROJECT") {rs -> assertNotNull (rs [0]) assertNotNull (rs [1]) assertNotNull (rs [2])}

5.3. Paginacija

Rezultate možemo lako razvrstati na stranice, tj. Učitati samo podskup počevši od nekog odmaka pa sve do nekog maksimalnog broja redaka. To je, na primjer, uobičajena stvar u web aplikacijama.

svakiRed i povezane metode imaju preopterećenja koja prihvaćaju pomak i maksimalan broj vraćenih redaka:

def offset = 1 def maxResults = 1 def redovi = sql.rows ('SELECT * FROM PROJECT ORDER BY NAME', offset, maxResults) assertEquals (1, rows.size ()) assertEquals ('REST with Spring', lines [0 ].Ime)

Evo, redaka metoda vraća popis redaka, umjesto da ih ponavlja kao svakiRed.

6. Parametrizirani upiti i izjave

Upiti i izrazi najčešće nisu potpuno fiksni u vrijeme sastavljanja; obično imaju statički i dinamički dio, u obliku parametara.

Ako razmišljate o spajanju nizova, zaustavite se i pročitajte o ubrizgavanju SQL-a!

Ranije smo spomenuli da metode koje smo vidjeli u prethodnim odjeljcima imaju mnogo preopterećenja za različite scenarije.

Uvedimo ona preopterećenja koja se bave parametrima u SQL upitima i izrazima.

6.1. Žice s rezerviranim mjestima

U stilu sličnom običnom JDBC-u, možemo koristiti pozicijske parametre:

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

ili možemo koristiti imenovane parametre s mapom:

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

Ovo djeluje za izvršiti, executeUpdate, redaka i svakiRed. executeInsert podržava i parametre, ali njegov je potpis malo drugačiji i lukaviji.

6.2. Groovy žice

Također se možemo odlučiti za Groovier stil koristeći GStrings s rezerviranim mjestima.

Sve metode koje smo vidjeli ne zamjenjuju rezervirana mjesta u GStringsu na uobičajeni način; već ih ubacuju kao JDBC parametre, osiguravajući da se sintaksa SQL točno sačuva, bez potrebe za citiranjem ili izbjegavanjem, a time i bez rizika od ubrizgavanja.

Ovo je sasvim u redu, sigurno i Groovy:

def name = 'REST with Spring' def url = 'github.com/eugenp/REST-With-Spring' sql.execute "INSERT IN TO PROJECT (NAME, URL) VRIJEDNOSTI ($ {name}, $ {url})"

7. Transakcije i veze

Do sada smo preskočili vrlo važnu brigu: transakcije.

Zapravo uopće nismo razgovarali o tome kako Groovy Sql upravlja i vezama.

7.1. Kratkotrajne veze

U dosad predstavljenim primjerima, svaki upit ili iskaz poslan je u bazu podataka pomoću nove, namjenske veze. Sql prekida vezu čim se operacija završi.

Naravno, ako koristimo spremište veza, utjecaj na izvedbu mogao bi biti mali.

Još, ako želimo izdati više DML izraza i upita kao jednu, atomsku operaciju, trebamo transakciju.

Također, da bi transakcija uopće bila moguća, potrebna nam je veza koja obuhvaća više izjava i upita.

7.2. Transakcije s predmemoriranom vezom

Groovy SQL ne dopušta nam da izravno stvaramo ili pristupimo transakcijama.

Umjesto toga koristimo withTransaction metoda sa zatvaranjem:

sql.withTransaction {sql.execute "" "INSERT INTO PROJECT (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')" "" sql.execute "" "INSERT INTO PROJECT (NAME, URL ) VRIJEDNOSTI ('ODMOR s proljećem', 'github.com/eugenp/REST-With-Spring') "" "}

Unutar zatvarača koristi se jedna veza baze podataka za sve upite i izraze.

Nadalje, transakcija se automatski izvršava kada prestaje zatvaranje, osim ako ne izađe prerano zbog iznimke.

Međutim, također možemo ručno predati ili vratiti trenutnu transakciju metodama u Sql razred:

sql.withTransaction {sql.execute "" "INSERT INTO PROJECT (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')" "" sql.commit () sql.execute "" "INSERT INTO VRIJEDNOSTI PROJEKTA (IME, URL) ('OSTALO s proljećem', 'github.com/eugenp/REST-With-Spring') "" "sql.rollback ()}

7.3. Predmemorirane veze bez transakcije

Konačno, za ponovnu upotrebu veze baze podataka bez gore opisane semantike transakcije koristimo cacheConnection:

sql.cacheConnection {sql.execute "" "INSERT IN TO PROJECT (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')" "" throw new Exception ('This does not roll back')}

8. Zaključci i daljnje čitanje

U ovom smo članku pogledali Groovy SQL modul i kako poboljšava i pojednostavljuje JDBC zatvaračima i Groovy nizovima.

Tada sa sigurnošću možemo zaključiti da obični stari JDBC izgleda malo modernije s posipom Groovyja!

Nismo razgovarali o svakoj pojedinoj značajci Groovy SQL-a; na primjer, izostavili smo serijsku obradu, pohranjene procedure, metapodatke i druge stvari.

Za daljnje informacije pogledajte Groovy dokumentaciju.

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.


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