Útmutató az sql2o JDBC burkolóhoz

1. Bemutatkozás

Ebben az oktatóanyagban megnézzük az Sql2o-t, egy kicsi és gyors könyvtárat a relációs adatbázis-hozzáféréshez az idiomatikus Java-ban.

Érdemes megemlíteni, hogy bár az Sql2o úgy működik, hogy lekérdezési eredményeket hozzárendel a POJO-khoz (sima régi Java objektumok), ez nem egy teljes ORM megoldás, mint például a Hibernate.

2. Az Sql2o beállítása

Az Sql2o egyetlen jar fájl, amelyet könnyedén hozzáadhatunk projektünk függőségeihez:

 org.sql2o sql2o 1.6.0 

A példáinkban a HSQL-t, a beágyazott adatbázist is felhasználjuk; a követés érdekében felvehetjük azt is:

 org.hsqldb hsqldb 2.4.0 teszt 

A Maven Central üzemelteti a legújabb verzióját sql2o és a HSQLDB.

3. Csatlakozás az adatbázishoz

A kapcsolat létrehozásához a Sql2o osztály:

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

Itt megadjuk a kapcsolat URL-jét, felhasználónevét és jelszavát konstruktor paramétereként.

A Sql2o Az objektum szálbiztos, és megoszthatjuk az alkalmazásban.

3.1. Használva Adatforrás

A legtöbb alkalmazásban a Adatforrásnyers helyett DriverManager kapcsolat létrehozására, esetleg egy kapcsolati készlet kihasználására, vagy további csatlakozási paraméterek megadására. Ne aggódjon, az Sql2o lefedett minket:

Sql2o sql2o = új Sql2o (adatforrás);

3.2. Munka a kapcsolatokkal

Pusztán a Sql2o objektum nem hoz létre kapcsolatot az adatbázissal.

Helyette, használjuk a nyisd ki módszer a Kapcsolat tárgy (vegye figyelembe, hogy ez nem JDBC Kapcsolat). Mivel Kapcsolat van Automatikusan zárható, becsomagolhatjuk egy try-with-resources blokkba:

próbáld meg (Csatlakozási kapcsolat = sql2o.open ()) {// használja a kapcsolatot}

4. Helyezze be és frissítse a kimutatásokat

Most hozzunk létre egy adatbázist, és tegyünk bele néhány adatot. A bemutató során egy egyszerű táblázatot fogunk használni projekt:

connection.createQuery ("tábla projekt létrehozása" + "(id egész azonosító, varchar név (50), urch varchar (100))"). executeUpdate ();

executeUpdate visszaadja a Kapcsolat objektumot, hogy több hívást láncolhassunk. Ezután, ha meg akarjuk tudni az érintett sorok számát, használjuk getResult:

assertEquals (0, connection.getResult ());

Az imént látott mintát alkalmazzuk - createQuery és executeUpdate -minden DDL, INSERT és UPDATE utasításhoz.

4.1. Generált kulcsértékek megszerzése

Bizonyos esetekben azonban érdemes visszakapni a generált kulcsértékeket. Ezek azok a kulcsoszlopok értékei, amelyek automatikusan kiszámításra kerülnek (például bizonyos adatbázisok automatikus növelésének használata esetén).

Két lépésben tesszük. Először egy további paraméterrel a createQuery:

Lekérdezés = connection.createQuery ("beillesztés a projektbe (név, URL)" + "értékek ('oktatóanyagok', 'github.com/eugenp/tutorials')", igaz);

Aztán hivatkozva getKey a kapcsolaton:

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

Ha a kulcsok többek, akkor használjuk getKeys ahelyett, hogy egy tömböt ad vissza:

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

5. Adatok kinyerése az adatbázisból

Térjünk most a lényegre: SELECT lekérdezések és az eredménykészletek leképezése Java objektumokra.

Először meg kell határoznunk egy POJO osztályt getterekkel és beállítókkal, hogy képviseljük a projekt táblázatot:

nyilvános osztály Projekt {hosszú id; privát karakterlánc neve; privát karakterlánc URL; // Normál mérőeszközök és beállítók}

Ezután, mint korábban, megírjuk a lekérdezésünket:

Lekérdezés = connection.createQuery ("válasszon * a projekt sorrendjéből id szerint");

Ezúttal azonban egy új módszert fogunk használni, executeAndFetch:

Lista lista = lekérdezés.executeAndFetch (Projekt.osztály);

Mint láthatjuk, a módszer az eredmények osztályát veszi paraméterként, amelyhez az Sql2o feltérképezi az adatbázisból érkező nyers eredményhalmaz sorait.

5.1. Oszloptérképezés

Az Sql2o oszlopokat térképez fel a JavaBean tulajdonságaihoz név szerint, kis- és nagybetűk.

A névadási szokások azonban eltérnek a Java és a relációs adatbázisok között. Tegyük fel, hogy projektjeinkhez hozzáadunk egy létrehozási dátum tulajdonságot:

nyilvános osztály Projekt {hosszú id; privát karakterlánc neve; privát karakterlánc URL; privát Dátum létrehozásaDátum; // Normál mérőeszközök és beállítók}

Az adatbázis-sémában valószínűleg ugyanazt a tulajdonságot fogjuk hívni létrehozás dátuma.

Természetesen álnevet használhatunk kérdéseinkben:

Lekérdezés = connection.createQuery ("válassza ki a projekt nevét, URL-jét, létrehozási dátumát a létrehozás dátumaként");

Ez azonban unalmas, és elveszítjük a használat lehetőségét válassza a * lehetőséget.

Egy másik lehetőség az Sql2o feltérképezésre utasítása létrehozás dátuma nak nek létrehozás dátuma. Vagyis elmondhatjuk a lekérdezést a leképezésről:

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

Ez jó, ha használjuk létrehozás dátuma takarékosan, néhány kérdésben; ha azonban egy nagyobb projektben széles körben alkalmazzák, akkor unalmas és hibára hajlamos ugyanaz a tény újra és újra elmondani.

Szerencsére mi is adja meg a leképezéseket globálisan:

Térkép leképezések = new HashMap (); mappings.put ("CREATION_DATE", "creationDate"); sql2o.setDefaultColumnMappings (leképezések);

Természetesen ez okozza a létrehozás dátuma feltérképezni létrehozás dátuma, tehát ez egy újabb ok arra, hogy a neveket az adataink meghatározása során egységesen tartsuk.

5.2. Skaláris eredmények

Néha egyetlen skaláris eredményt szeretnénk kinyerni egy lekérdezésből. Például, amikor meg kell számolnunk a rekordok számát.

Ezekben az esetekben az osztály meghatározása és egy lista feletti iterálás, amelyről tudjuk, hogy egyetlen elemet tartalmaz, túlzott. Így, Az Sql2o tartalmazza a végrehajtaniScalar módszer:

Lekérdezés = connection.createQuery ("select count (*) from project"); assertEquals (2, query.executeScalar (Egész.osztály));

Itt adjuk meg a visszatérési típust Egész szám. Ez azonban opcionális, és hagyhatjuk, hogy a mögöttes JDBC illesztőprogram döntsön.

5.3. Komplex eredmények

Néha előfordulhat, hogy a bonyolult lekérdezések (például a jelentésekhez) nem könnyen térképezhetők fel egy Java objektumra. Azt is eldönthetjük, hogy nem akarunk egy Java osztályt kódolni, hogy csak egyetlen lekérdezésben használjuk.

Így, Az Sql2o lehetővé teszi az alacsonyabb szintű, dinamikus leképezést táblázatos adatszerkezetekhez is. Ehhez a executeAndFetchTable módszer:

Lekérdezés = connection.createQuery ("válasszon * a projekt sorrendjéből id szerint"); Táblázat tábla = query.executeAndFetchTable ();

Ezután kinyerhetjük a térképek listáját:

Lista list = table.asList (); assertEquals ("oktatóanyagok", list.get (0) .get ("név"));

Alternatív megoldásként feltérképezhetjük az adatokat egy listára Sor objektumok, amelyek oszlopnevektől értékekhez való hozzárendelések, hasonlóak a ResultSets:

Sorok felsorolása = table.rows (); assertEquals ("oktatóanyagok", rows.get (0) .getString ("név"));

6. Kötelező lekérdezési paraméterek

Sok SQL lekérdezés rögzített felépítésű, néhány paraméterezett résszel. Lehet, hogy naivan megírjuk azokat a részben dinamikus lekérdezéseket karakterlánc-összefűzéssel.

Az Sql2o azonban lehetővé teszi a paraméterezett lekérdezéseket, így:

  • Kerüljük az SQL injekciós támadásokat
  • Lehetővé tesszük az adatbázis számára a gyakran használt lekérdezések gyorsítótárazását és a teljesítmény növelését
  • Végül megkíméljük az olyan összetett típusok kódolásától, mint a dátumok és idők

Tehát az Sql2o-val megnevezett paramétereket használhatunk a fentiek teljesítéséhez. A paramétereket kettősponttal vezetjük be, és a addParameter módszer:

Lekérdezés = connection.createQuery ("beszúrás a projektbe (név, URL) értékek (: név,: url)") .addParameter ("név", "REST tavasszal") .addParameter ("url", "github.com / eugenp / REST-With-Spring "); assertEquals (1, query.executeUpdate (). getResult ());

6.1. Kötés POJO-tól

Az Sql2o a paraméterek megkötésének alternatív módját kínálja: POJO-k használatával mint a forrás. Ez a technika különösen alkalmas, ha egy lekérdezésnek sok paramétere van, és mindegyik ugyanarra az entitásra vonatkozik. Tehát, mutassuk be a megkötözni módszer:

Projekt projekt = new Project (); project.setName ("REST with Spring"); project.setUrl ("github.com/eugenp/REST-With-Spring"); connection.createQuery ("beszúrás a projektbe (név, URL) értékek (: név,: url)") .bind (project) .executeUpdate (); assertEquals (1, connection.getResult ());

7. Tranzakciók és kötegelt lekérdezések

Tranzakcióval több SQL utasítást adhatunk ki egyetlen atomi műveletként. Vagyis vagy sikerül, vagy tömegesen kudarcot vall, köztes eredmények nélkül. Valójában a tranzakciók a relációs adatbázisok egyik legfontosabb jellemzője.

A tranzakció megnyitásához a beginTransaction módszer helyett nyisd ki módszer, amelyet eddig használtunk:

try (Connection connection = sql2o.beginTransaction ()) {// itt, a tranzakció aktív}

Amikor a végrehajtás elhagyja a blokkot, Az Sql2o automatikusan visszavonja a tranzakciót ha még mindig aktív.

7.1. Kézi véglegesítés és visszagörgetés

Azonban, a tranzakciót kifejezetten leköthetjük vagy visszavonhatjuk a megfelelő módszerekkel:

try (Csatlakozási kapcsolat = sql2o.beginTransaction ()) {logikai tranzakcióSikeres = hamis; // hajtson végre néhány műveletet, ha (tranzakcióSikeres) {connection.commit (); } else {connection.rollback (); }}

Vegye figyelembe, hogy mindkét elkövetni és visszagörgetés fejezze be a tranzakciót. Az ezt követő utasítások tranzakció nélkül futnak, így nem kerülnek automatikusan visszagörgetésre a blokk végén.

Elvégezhetjük vagy visszavonhatjuk a tranzakciót anélkül, hogy befejeznénk:

próbálkozzon (Connection connection = sql2o.beginTransaction ()) {List list = connection.createQuery ("select * from project") .executeAndFetchTable () .asList (); assertEquals (0, list.size ()); // beilleszt vagy frissít néhány adatkapcsolatot.rollback (false); // más beillesztési vagy frissítési lekérdezés végrehajtása} // implicit visszagörgetési próbálkozás (Connection connection = sql2o.beginTransaction ()) {List list = connection.createQuery ("select * from project") .executeAndFetchTable () .asList (); assertEquals (0, list.size ()); }

7.2. Kötegelt műveletek

Amikor szükségünk van rá kiadja ugyanazt az utasítást sokszor, különböző paraméterekkel, A kötegelt futtatás nagy teljesítményelőnyt jelent.

Szerencsére az eddig ismertetett két technika - a paraméterezett lekérdezések és tranzakciók - kombinálásával elég egyszerű futtatni őket kötegenként:

  • Először csak egyszer hozzuk létre a lekérdezést
  • Ezután összekapcsoljuk a paramétereket és felhívjuk addToBatch a lekérdezés minden egyes példányához
  • Végül felhívjuk executeBatch:
try (Csatlakozási kapcsolat = sql2o.beginTransaction ()) {Lekérdezés = connection.createQuery ("beillesztés a projektbe (név, URL)" + "értékek (: név,: url)"); for (int i = 0; i <1000; i ++) {query.addParameter ("név", "oktatóanyagok" + i); query.addParameter ("url", "//github.com/eugenp/tutorials" + i); query.addToBatch (); } query.executeBatch (); connection.commit (); } try (Csatlakozási kapcsolat = sql2o.beginTransaction ()) {assertEquals (1000L, connection.createQuery ("select count (*) from project"). executeScalar ()); }

7.3. Lusta Fetch

Fordítva, Ha egyetlen lekérdezés nagyon sok eredményt ad vissza, akkor az összes átalakítása és a listában való tárolás megnehezíti a memóriát.

Tehát az Sql2o támogatja a lusta módot, ahol a sorokat egyenként adják vissza és hozzárendelik:

Lekérdezés = connection.createQuery ("select * from project"); próbálkozzon (ResultSetIterable projects = query.executeAndFetchLazy (Project.class)) {for (Project p: projektek) {// csináljon valamit a projekttel}}

Vegye figyelembe, hogy ResultSetIterable van Automatikusan zárható és azzal hivatott használni erőforrásokkal próbálkozzon hogy lezárja az alapul szolgáló ResultSet mikor kész.

8. Következtetések

Ebben az oktatóanyagban bemutattuk az Sql2o könyvtár és a leggyakoribb használati minták áttekintését. További információ a GitHub Sql20 wiki-jében található.

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