JDBC Groovyvel

1. Bemutatkozás

Ebben a cikkben megvizsgáljuk, hogyan lehet lekérdezni a relációs adatbázisokat a JDBC segítségével, idiomatikus Groovy segítségével.

Bár a JDBC viszonylag alacsony szintű, a legtöbb ORM és más magas szintű adatelérési könyvtárak alapja a JVM-en. És a JDBC-t természetesen Groovy-ban is használhatjuk, természetesen; azonban meglehetősen nehézkes API-val rendelkezik.

Szerencsénkre a Groovy standard könyvtár a JDBC-re épít, hogy tiszta, egyszerű, de mégis hatékony felületet mutasson be. Tehát felfedezzük a Groovy SQL modult.

A JDBC-t egyszerű Groovy-ban fogjuk megvizsgálni, és nem veszünk figyelembe semmilyen keretet, mint például a Spring, amelyhez más útmutatók is vannak.

2. JDBC és Groovy Setup

Be kell foglalnunk a groovy-sql modul a függőségeink között:

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

Nem szükséges kifejezetten felsorolni, ha a groovy-all-ot használjuk:

 org.codehaus.groovy groovy-all 2.4.13 

Megtalálhatjuk a legújabb verzióját groovy, groovy-sql és nagyszerű a Maven Central-on.

3. Csatlakozás az adatbázishoz

Az első dolog, amit meg kell tennünk annak érdekében, hogy az adatbázissal dolgozzunk, az a csatlakozás hozzá.

Bemutatjuk a groovy.sql.Sql osztály, amelyet az adatbázisban a Groovy SQL modullal végzett összes művelethez használunk.

Példája Sql egy olyan adatbázist képvisel, amelyen működni akarunk.

Azonban, példánya Sqlnem egyetlen adatbázis-kapcsolat. A kapcsolatokról később beszélünk, most ne aggódjunk ezek miatt; tegyük fel, hogy minden varázslatosan működik.

3.1. Csatlakozási paraméterek megadása

A cikkben egy HSQL adatbázist fogunk használni, amely egy könnyű relációs DB, amelyet főleg tesztek során használnak.

Az adatbázis-kapcsolathoz URL-re, illesztőprogramra és hozzáférési hitelesítő adatokra van szükség:

Térkép dbConnParams = [url: 'jdbc: hsqldb: mem: testDB', felhasználó: 'sa', jelszó: '', illesztőprogram: 'org.hsqldb.jdbc.JDBCDriver']

Itt választottuk az a használatát Térkép, bár nem ez az egyetlen lehetséges választás.

Ezután kapcsolatot szerezhetünk a Sql osztály:

def sql = Sql.newInstance (dbConnParams)

A következő szakaszokban megtudjuk, hogyan kell használni.

Amikor befejeztük, mindig fel kell szabadítanunk a kapcsolódó erőforrásokat:

sql.close ()

3.2. Használva Adatforrás

Különösen az alkalmazáskiszolgálón futó programokban szokás adatforrást használni az adatbázishoz való csatlakozáshoz.

Továbbá, ha egyesíteni akarjuk a kapcsolatokat, vagy a JNDI-t akarjuk használni, akkor az adatforrás a legtermészetesebb lehetőség.

Groovyé Sql osztály elfogadja az adatforrásokat:

def sql = Sql.newInstance (adatforrás)

3.3. Automatikus erőforrás-kezelés

Ne feledje, hogy hívjon Bezárás() amikor végeztünk egy Sql az eset unalmas; a gépek végül is sokkal jobban emlékeznek a dolgokra, mint mi.

Val vel Sql becsomagolhatjuk kódunkat, és felhívhatjuk Groovy-t Bezárás() automatikusan, amikor a vezérlés elhagyja, még kivételek esetén is:

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

4. Nyilatkozatok kiadása az adatbázis ellen

Most folytathatjuk az érdekes dolgokat.

Az adatbázissal szembeni nyilatkozat kiadásának legegyszerűbb és legspecializálatlanabb módja a végrehajtani módszer:

sql.execute "tábla létrehozása PROJECT (id egész szám nem null, név varchar (50), url varchar (100))"

Elméletileg mind a DDL / DML utasítások, mind a lekérdezések esetében működik; a fenti egyszerű űrlap azonban nem kínál módot a lekérdezési eredmények visszakeresésére. A lekérdezéseket későbbre hagyjuk.

A végrehajtani A módszer több túlterhelt verzióval rendelkezik, de megint megnézzük ennek és más módszereknek a fejlettebb felhasználási eseteit a későbbi szakaszokban.

4.1. Adatok beszúrása

Az adatok kis mennyiségben és egyszerű forgatókönyvekbe történő beszúrásához a végrehajtani A korábban tárgyalt módszer teljesen rendben van.

Azonban azokra az esetekre, amikor oszlopokat generáltunk (például szekvenciákkal vagy automatikus növekedéssel), és tudni szeretnénk a létrehozott értékeket, létezik külön módszer: executeInsert.

Ami végrehajtani, most megvizsgáljuk a rendelkezésre álló legegyszerűbb módszeres túlterhelést, bonyolultabb változatokat hagyva egy későbbi szakasz számára.

Tehát tegyük fel, hogy van egy táblázatunk egy automatikus növekedésű elsődleges kulccsal (azonosság a HSQLDB nyelvhasználatban):

sql.execute "tábla létrehozása PROJECT (ID IDENTITY, NAME VARCHAR (50), URL VARCHAR (100))"

Helyezzünk be egy sort a táblázatba, és mentsük el az eredményt egy változóba:

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

executeInsert pontosan úgy viselkedik, mint végrehajtani, de mit ad vissza?

Kiderült, hogy a visszatérési érték egy mátrix: sorai a beszúrt sorok (ne feledje, hogy egyetlen utasítás több sort is beszúrhat), oszlopai pedig a generált értékek.

Bonyolultnak hangzik, de esetünkben, amely messze a leggyakoribb, egyetlen sor és egyetlen generált érték létezik:

assertEquals (0, azonosítók [0] [0])

Egy későbbi beillesztés 1 generált értéket ad vissza:

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

4.2. Adatok frissítése és törlése

Hasonlóképpen létezik külön módszer az adatok módosítására és törlésére: executeUpdate.

Ez megint különbözik a végrehajtani csak a visszatérési értékében, és csak a legegyszerűbb formáját vesszük szemügyre.

A visszatérési érték ebben az esetben egy egész szám, az érintett sorok száma:

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

5. Az adatbázis lekérdezése

A dolgok akkor kezdenek Groovyt kapni, amikor lekérdezzük az adatbázist.

A JDBC kezelése ResultSet osztály nem éppen szórakoztató. Számunkra szerencsére Groovy szép absztrakciót kínál mindezek felett.

5.1. Ismétlődő a lekérdezési eredmények felett

Míg a hurkok olyan régi stílusúak, manapság mindannyian bezárások vagyunk.

És Groovy itt van, hogy megfeleljen az ízlésünknek:

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

A eachRow metódus kiadja a lekérdezésünket az adatbázissal szemben, és lezárást hív minden sorra.

Ahogy látjuk, egy sort a GroovyResultSet, amely a sima régi kiterjesztése ResultSet néhány hozzáadott finomsággal. Olvasson tovább, ha többet szeretne megtudni róla.

5.2. Az eredményhalmazok elérése

Az összes ResultSet mód, GroovyResultSet néhány kényelmes segédprogramot kínál.

Főként az oszlopneveknek megfelelő elnevezett tulajdonságokat tárja fel:

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

Vegye figyelembe, hogy a tulajdonságok nem különböztetik a kis- és nagybetűket.

GroovyResultSet oszlopokhoz is hozzáférést kínál nulla alapú index használatával:

sql.eachRow ("KIVÁLASZTÁS A PROJEKTBŐL") {rs -> assertNotNull (rs [0]) assertNotNull (rs [1]) assertNotNull (rs [2])}

5.3. Lapszámozás

Könnyedén átlapozhatjuk az eredményeket, vagyis csak egy részhalmazot tölthetünk fel valamilyen eltolástól a sorok maximális számáig. Ez általános probléma például a webes alkalmazásokban.

eachRow és a kapcsolódó módszerek túlterheléssel rendelkeznek, amelyek elfogadják az eltolást és a maximálisan visszaadott sorok számát:

def offset = 1 def maxResults = 1 def sor = sql.rows ('KIVÁLASZTÁS * A PROJEKT RENDELÉSÉBŐL NÉVBEN, offset, maxResults) assertEquals (1, rows.size ()) assertEquals (' REST with Spring ', sorok [0 ].név)

Itt a sorok A metódus a sorok listáját adja vissza, ahelyett, hogy iterálná őket eachRow.

6. Paraméterezett lekérdezések és kimutatások

Gyakrabban a lekérdezések és utasítások nem teljesen vannak rögzítve a fordítás idején; általában statikus és dinamikus részük van, paraméterek formájában.

Ha a karakterlánc összefűzésére gondol, álljon meg most és olvassa el az SQL injekciót!

Korábban említettük, hogy az előző szakaszokban látott módszerek számos túlterhelést tartalmaznak különböző forgatókönyvekhez.

Bemutatjuk azokat a túlterheléseket, amelyek paraméterekkel foglalkoznak az SQL lekérdezésekben és utasításokban.

6.1. Húrok helyőrzőkkel

A sima JDBC-hez hasonló stílusban helyzeti paramétereket használhatunk:

sql.execute ('INSERT INTO PROJECT (Név, URL) ÉRTÉKEK (?,?)', 'oktatóanyagok', 'github.com/eugenp/tutorials')

vagy használhatunk megnevezett paramétereket egy térképpel:

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

Ez működik végrehajtani, executeUpdate, sorok és eachRow. executeInsert támogatja a paramétereket is, de az aláírása kicsit más és bonyolultabb.

6.2. Groovy vonósok

Választhatunk Groovier stílust is a helyőrzőkkel ellátott GStrings használatával.

Az összes látott módszer nem helyettesíti a helyőrzőket a GStrings-ben a szokásos módon; Inkább JDBC-paraméterként illesztik be őket, biztosítva az SQL-szintaxis megfelelő megőrzését, nem kell semmit sem idézni, sem pedig elkerülni, és ezáltal nem jelent veszélyt az injekcióra.

Ez teljesen rendben van, biztonságos és Groovy:

def name = 'Pihenés tavasszal' def url = 'github.com/eugenp/REST-With-Spring' sql.execute "INSERT INTO PROJECT (NAME, URL) VALUES ($ {name}, $ {url})"

7. Tranzakciók és kapcsolatok

Eddig kihagytunk egy nagyon fontos problémát: a tranzakciókat.

Valójában egyáltalán nem beszéltünk arról, hogy van Groovy Sql a kapcsolatokat is kezeli.

7.1. Rövid életű kapcsolatok

Az eddig bemutatott példákban minden egyes lekérdezést vagy utasítást egy új, dedikált kapcsolat segítségével küldtek az adatbázisba. Sql amint a művelet befejeződik, bezárja a kapcsolatot.

Természetesen, ha kapcsolatkészletet használunk, a teljesítményre gyakorolt ​​hatás kicsi lehet.

Még mindig, ha több DML utasítást és lekérdezést akarunk kiadni egyetlen, atomi műveletként, tranzakcióra van szükségünk.

Emellett ahhoz, hogy egy tranzakció eleve lehetséges legyen, szükségünk van egy kapcsolatra, amely több utasításon és lekérdezésen átível.

7.2. Tranzakciók gyorsítótárazott kapcsolattal

A Groovy SQL nem teszi lehetővé, hogy tranzakciókat kifejezetten hozzunk létre vagy férjünk hozzá.

Ehelyett a withTransaction módszer lezárással:

sql.withTransaction {sql.exe ) ÉRTÉKEK ('REST with Spring', 'github.com/eugenp/REST-With-Spring') "" "}

A bezáráson belül egyetlen adatbázis-kapcsolatot használnak minden lekérdezéshez és utasításhoz.

Ezenkívül a tranzakció automatikusan lezárul, amikor a lezárás megszűnik, kivéve, ha egy kivétel miatt hamarosan kilép.

Ugyanakkor manuálisan is elvégezhetjük vagy visszaguríthatjuk az aktuális tranzakciót a Sql osztály:

sql.withTransaction {sql.execute "" "INSERT INTO PROJECT (NAME, URL) VALUES ('tutorials', 'github.com/eugenp/tutorials')" "" sql.commit () sql.execute "" "INSERT INTO PROJEKT (NÉV, URL) ÉRTÉKEI ('REST with Spring', 'github.com/eugenp/REST-With-Spring') "" "sql.rollback ()}

7.3. Gyorsítótárazott kapcsolatok tranzakció nélkül

Végül egy adatbázis-kapcsolat újrafelhasználásához a fent leírt tranzakciós szemantika nélkül használjuk cacheConnection:

sql.cacheConnection {sql.execute "" "INSERT INTO PROJECT (Név, URL) ÉRTÉKEI ('tutorials', 'github.com/eugenp/tutorials')" "" dobjon új kivételt ('Ez nem gördül vissza')}

8. Következtetések és további olvasmányok

Ebben a cikkben megvizsgáltuk a Groovy SQL modult, és hogyan javítja és egyszerűsíti a JDBC-t bezárásokkal és Groovy-húrokkal.

Ezután nyugodtan megállapíthatjuk, hogy a sima régi JDBC egy kicsit modernebbnek tűnik egy Groovy-szórással!

Nem beszéltünk a Groovy SQL minden egyes tulajdonságáról; például kihagytuk a kötegelt feldolgozást, a tárolt eljárásokat, a metaadatokat és egyéb dolgokat.

További információ a Groovy dokumentációjában található.

Ezeknek a példáknak és kódrészleteknek a megvalósítása megtalálható a GitHub projektben - ez egy Maven projekt, ezért könnyen importálhatónak és futtathatónak kell lennie.